RocksDB Doxygen
로딩중...
검색중...
일치하는것 없음
ROCKSDB_NAMESPACE::DBImpl 클래스 참조

#include <db_impl.h>

ROCKSDB_NAMESPACE::DBImpl에 대한 상속 다이어그램 :
ROCKSDB_NAMESPACE::DBImpl에 대한 협력 다이어그램:

클래스

struct  BGFlushArg
 
struct  BGJobLimits
 
struct  ColumnFamilySuperVersionPair
 
struct  CompactionArg
 
struct  FlushRequest
 
struct  FlushThreadArg
 
struct  GetImplOptions
 
struct  LogContext
 
struct  LogFileNumberSize
 
struct  LogWriterNumber
 
struct  ManualCompactionState
 
struct  MultiGetKeyRangePerCf
 
struct  PrepickedCompaction
 
struct  PurgeFileInfo
 
struct  RecoveredTransaction
 
class  RecoveryContext
 
class  WBMStallInterface
 
struct  WriteContext
 

Public 멤버 함수

 DBImpl (const DBOptions &options, const std::string &dbname, const bool seq_per_batch=false, const bool batch_per_txn=true, bool read_only=false)
 
 DBImpl (const DBImpl &)=delete
 
void operator= (const DBImpl &)=delete
 
virtual ~DBImpl ()
 
Status Resume () override
 
Status Put (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &value) override
 
Status Put (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &ts, const Slice &value) override
 
Status PutEntity (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const WideColumns &columns) override
 
Status PutEntity (const WriteOptions &options, const Slice &key, const AttributeGroups &attribute_groups) override
 
Status Merge (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &value) override
 
Status Merge (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &ts, const Slice &value) override
 
Status Delete (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key) override
 
Status Delete (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &ts) override
 
Status SingleDelete (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key) override
 
Status SingleDelete (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &ts) override
 
Status DeleteRange (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &begin_key, const Slice &end_key) override
 
Status DeleteRange (const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &begin_key, const Slice &end_key, const Slice &ts) override
 
Status Write (const WriteOptions &options, WriteBatch *updates) override
 
Status WriteWithCallback (const WriteOptions &options, WriteBatch *updates, UserWriteCallback *user_write_cb) override
 
Status Get (const ReadOptions &_read_options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *value, std::string *timestamp) override
 
Status GetEntity (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, PinnableWideColumns *columns) override
 
Status GetEntity (const ReadOptions &options, const Slice &key, PinnableAttributeGroups *result) override
 
Status GetMergeOperands (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *merge_operands, GetMergeOperandsOptions *get_merge_operands_options, int *number_of_operands) override
 
void MultiGet (const ReadOptions &_read_options, const size_t num_keys, ColumnFamilyHandle **column_families, const Slice *keys, PinnableSlice *values, std::string *timestamps, Status *statuses, const bool sorted_input=false) override
 
void MultiGetWithCallback (const ReadOptions &_read_options, ColumnFamilyHandle *column_family, ReadCallback *callback, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *sorted_keys)
 
void MultiGetEntity (const ReadOptions &options, ColumnFamilyHandle *column_family, size_t num_keys, const Slice *keys, PinnableWideColumns *results, Status *statuses, bool sorted_input) override
 
void MultiGetEntity (const ReadOptions &options, size_t num_keys, ColumnFamilyHandle **column_families, const Slice *keys, PinnableWideColumns *results, Status *statuses, bool sorted_input) override
 
void MultiGetEntity (const ReadOptions &options, size_t num_keys, const Slice *keys, PinnableAttributeGroups *results) override
 
void MultiGetEntityWithCallback (const ReadOptions &read_options, ColumnFamilyHandle *column_family, ReadCallback *callback, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *sorted_keys)
 
Status CreateColumnFamily (const ColumnFamilyOptions &cf_options, const std::string &column_family, ColumnFamilyHandle **handle) override
 
virtual Status CreateColumnFamily (const ReadOptions &read_options, const WriteOptions &write_options, const ColumnFamilyOptions &cf_options, const std::string &column_family, ColumnFamilyHandle **handle)
 
Status CreateColumnFamilies (const ColumnFamilyOptions &cf_options, const std::vector< std::string > &column_family_names, std::vector< ColumnFamilyHandle * > *handles) override
 
virtual Status CreateColumnFamilies (const ReadOptions &read_options, const WriteOptions &write_options, const ColumnFamilyOptions &cf_options, const std::vector< std::string > &column_family_names, std::vector< ColumnFamilyHandle * > *handles)
 
Status CreateColumnFamilies (const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles) override
 
virtual Status CreateColumnFamilies (const ReadOptions &read_options, const WriteOptions &write_options, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles)
 
Status DropColumnFamily (ColumnFamilyHandle *column_family) override
 
Status DropColumnFamilies (const std::vector< ColumnFamilyHandle * > &column_families) override
 
bool KeyMayExist (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, std::string *value, std::string *timestamp, bool *value_found=nullptr) override
 
IteratorNewIterator (const ReadOptions &_read_options, ColumnFamilyHandle *column_family) override
 
Status NewIterators (const ReadOptions &_read_options, const std::vector< ColumnFamilyHandle * > &column_families, std::vector< Iterator * > *iterators) override
 
const SnapshotGetSnapshot () override
 
void ReleaseSnapshot (const Snapshot *snapshot) override
 
std::unique_ptr< IteratorNewCoalescingIterator (const ReadOptions &options, const std::vector< ColumnFamilyHandle * > &column_families) override
 
std::unique_ptr< AttributeGroupIteratorNewAttributeGroupIterator (const ReadOptions &options, const std::vector< ColumnFamilyHandle * > &column_families) override
 
std::pair< Status, std::shared_ptr< const Snapshot > > CreateTimestampedSnapshot (SequenceNumber snapshot_seq, uint64_t ts)
 
std::shared_ptr< const SnapshotImplGetTimestampedSnapshot (uint64_t ts) const
 
void ReleaseTimestampedSnapshotsOlderThan (uint64_t ts, size_t *remaining_total_ss=nullptr)
 
Status GetTimestampedSnapshots (uint64_t ts_lb, uint64_t ts_ub, std::vector< std::shared_ptr< const Snapshot > > &timestamped_snapshots) const
 
bool GetProperty (ColumnFamilyHandle *column_family, const Slice &property, std::string *value) override
 
bool GetMapProperty (ColumnFamilyHandle *column_family, const Slice &property, std::map< std::string, std::string > *value) override
 
bool GetIntProperty (ColumnFamilyHandle *column_family, const Slice &property, uint64_t *value) override
 
bool GetAggregatedIntProperty (const Slice &property, uint64_t *aggregated_value) override
 
Status GetApproximateSizes (const SizeApproximationOptions &options, ColumnFamilyHandle *column_family, const Range *range, int n, uint64_t *sizes) override
 
void GetApproximateMemTableStats (ColumnFamilyHandle *column_family, const Range &range, uint64_t *const count, uint64_t *const size) override
 
Status CompactRange (const CompactRangeOptions &options, ColumnFamilyHandle *column_family, const Slice *begin, const Slice *end) override
 
Status CompactFiles (const CompactionOptions &compact_options, ColumnFamilyHandle *column_family, const std::vector< std::string > &input_file_names, const int output_level, const int output_path_id=-1, std::vector< std::string > *const output_file_names=nullptr, CompactionJobInfo *compaction_job_info=nullptr) override
 
Status PauseBackgroundWork () override
 
Status ContinueBackgroundWork () override
 
Status EnableAutoCompaction (const std::vector< ColumnFamilyHandle * > &column_family_handles) override
 
void EnableManualCompaction () override
 
void DisableManualCompaction () override
 
Status SetOptions (ColumnFamilyHandle *column_family, const std::unordered_map< std::string, std::string > &options_map) override
 
Status SetDBOptions (const std::unordered_map< std::string, std::string > &options_map) override
 
int NumberLevels (ColumnFamilyHandle *column_family) override
 
int MaxMemCompactionLevel (ColumnFamilyHandle *column_family) override
 
int Level0StopWriteTrigger (ColumnFamilyHandle *column_family) override
 
const std::string & GetName () const override
 
EnvGetEnv () const override
 
FileSystemGetFileSystem () const override
 
Options GetOptions (ColumnFamilyHandle *column_family) const override
 
DBOptions GetDBOptions () const override
 
Status Flush (const FlushOptions &options, ColumnFamilyHandle *column_family) override
 
Status Flush (const FlushOptions &options, const std::vector< ColumnFamilyHandle * > &column_families) override
 
Status FlushWAL (bool sync) override
 
virtual Status FlushWAL (const WriteOptions &write_options, bool sync)
 
bool WALBufferIsEmpty ()
 
Status SyncWAL () override
 
Status LockWAL () override
 
Status UnlockWAL () override
 
SequenceNumber GetLatestSequenceNumber () const override
 
Status IncreaseFullHistoryTsLow (ColumnFamilyHandle *column_family, std::string ts_low) override
 
Status GetFullHistoryTsLow (ColumnFamilyHandle *column_family, std::string *ts_low) override
 
Status GetDbIdentity (std::string &identity) const override
 
virtual Status GetDbIdentityFromIdentityFile (const IOOptions &opts, std::string *identity) const
 
Status GetDbSessionId (std::string &session_id) const override
 
ColumnFamilyHandleDefaultColumnFamily () const override
 
ColumnFamilyHandlePersistentStatsColumnFamily () const
 
Status Close () override
 
Status DisableFileDeletions () override
 
Status EnableFileDeletions () override
 
virtual bool IsFileDeletionsEnabled () const
 
Status GetStatsHistory (uint64_t start_time, uint64_t end_time, std::unique_ptr< StatsHistoryIterator > *stats_iterator) override
 
Status ResetStats () override
 
Status GetLiveFiles (std::vector< std::string > &, uint64_t *manifest_file_size, bool flush_memtable=true) override
 
Status GetSortedWalFiles (VectorWalPtr &files) override
 
Status GetSortedWalFilesImpl (VectorWalPtr &files, bool need_seqnos)
 
Status GetOpenWalSizes (std::map< uint64_t, uint64_t > &number_to_size)
 
Status GetCurrentWalFile (std::unique_ptr< WalFile > *current_log_file) override
 
Status GetCreationTimeOfOldestFile (uint64_t *creation_time) override
 
Status GetUpdatesSince (SequenceNumber seq_number, std::unique_ptr< TransactionLogIterator > *iter, const TransactionLogIterator::ReadOptions &read_options=TransactionLogIterator::ReadOptions()) override
 
Status DeleteFile (std::string name) override
 
Status DeleteFilesInRanges (ColumnFamilyHandle *column_family, const RangePtr *ranges, size_t n, bool include_end=true)
 
void GetLiveFilesMetaData (std::vector< LiveFileMetaData > *metadata) override
 
Status GetLiveFilesChecksumInfo (FileChecksumList *checksum_list) override
 
Status GetLiveFilesStorageInfo (const LiveFilesStorageInfoOptions &opts, std::vector< LiveFileStorageInfo > *files) override
 
void GetColumnFamilyMetaData (ColumnFamilyHandle *column_family, ColumnFamilyMetaData *metadata) override
 
void GetAllColumnFamilyMetaData (std::vector< ColumnFamilyMetaData > *metadata) override
 
Status SuggestCompactRange (ColumnFamilyHandle *column_family, const Slice *begin, const Slice *end) override
 
Status PromoteL0 (ColumnFamilyHandle *column_family, int target_level) override
 
Status IngestExternalFile (ColumnFamilyHandle *column_family, const std::vector< std::string > &external_files, const IngestExternalFileOptions &ingestion_options) override
 
Status IngestExternalFiles (const std::vector< IngestExternalFileArg > &args) override
 
Status CreateColumnFamilyWithImport (const ColumnFamilyOptions &options, const std::string &column_family_name, const ImportColumnFamilyOptions &import_options, const std::vector< const ExportImportFilesMetaData * > &metadatas, ColumnFamilyHandle **handle) override
 
Status ClipColumnFamily (ColumnFamilyHandle *column_family, const Slice &begin_key, const Slice &end_key) override
 
Status VerifyFileChecksums (const ReadOptions &read_options) override
 
Status VerifyChecksum (const ReadOptions &) override
 
Status VerifyChecksumInternal (const ReadOptions &read_options, bool use_file_checksum)
 
Status VerifyFullFileChecksum (const std::string &file_checksum_expected, const std::string &func_name_expected, const std::string &fpath, const ReadOptions &read_options)
 
Status StartTrace (const TraceOptions &options, std::unique_ptr< TraceWriter > &&trace_writer) override
 
Status EndTrace () override
 
Status NewDefaultReplayer (const std::vector< ColumnFamilyHandle * > &handles, std::unique_ptr< TraceReader > &&reader, std::unique_ptr< Replayer > *replayer) override
 
Status StartBlockCacheTrace (const TraceOptions &trace_options, std::unique_ptr< TraceWriter > &&trace_writer) override
 
Status StartBlockCacheTrace (const BlockCacheTraceOptions &options, std::unique_ptr< BlockCacheTraceWriter > &&trace_writer) override
 
Status EndBlockCacheTrace () override
 
Status StartIOTrace (const TraceOptions &options, std::unique_ptr< TraceWriter > &&trace_writer) override
 
Status EndIOTrace () override
 
Status GetPropertiesOfAllTables (ColumnFamilyHandle *column_family, TablePropertiesCollection *props) override
 
Status GetPropertiesOfTablesInRange (ColumnFamilyHandle *column_family, const Range *range, std::size_t n, TablePropertiesCollection *props) override
 
SystemClockGetSystemClock () const
 
Status GetImpl (const ReadOptions &read_options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *value)
 
Status GetImpl (const ReadOptions &read_options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *value, std::string *timestamp)
 
virtual Status GetImpl (const ReadOptions &options, const Slice &key, GetImplOptions &get_impl_options)
 
ArenaWrappedDBIterNewIteratorImpl (const ReadOptions &options, ColumnFamilyHandleImpl *cfh, SuperVersion *sv, SequenceNumber snapshot, ReadCallback *read_callback, bool expose_blob_index=false, bool allow_refresh=true)
 
virtual SequenceNumber GetLastPublishedSequence () const
 
virtual void SetLastPublishedSequence (SequenceNumber seq)
 
SequenceNumber TEST_GetLastVisibleSequence () const
 
virtual Status WriteWithCallback (const WriteOptions &write_options, WriteBatch *my_batch, WriteCallback *callback, UserWriteCallback *user_write_cb=nullptr)
 
SequenceNumber GetEarliestMemTableSequenceNumber (SuperVersion *sv, bool include_history)
 
Status GetLatestSequenceForKey (SuperVersion *sv, const Slice &key, bool cache_only, SequenceNumber lower_bound_seq, SequenceNumber *seq, std::string *timestamp, bool *found_record_for_key, bool *is_blob_index)
 
Status TraceIteratorSeek (const uint32_t &cf_id, const Slice &key, const Slice &lower_bound, const Slice upper_bound)
 
Status TraceIteratorSeekForPrev (const uint32_t &cf_id, const Slice &key, const Slice &lower_bound, const Slice upper_bound)
 
const SnapshotGetSnapshotForWriteConflictBoundary ()
 
virtual Status CheckConsistency ()
 
Status RunManualCompaction (ColumnFamilyData *cfd, int input_level, int output_level, const CompactRangeOptions &compact_range_options, const Slice *begin, const Slice *end, bool exclusive, bool disallow_trivial_move, uint64_t max_file_num_to_ignore, const std::string &trim_ts, int *final_output_level=nullptr)
 
InternalIteratorNewInternalIterator (const ReadOptions &read_options, Arena *arena, SequenceNumber sequence, ColumnFamilyHandle *column_family=nullptr, bool allow_unprepared_value=false)
 
InternalIteratorNewInternalIterator (const ReadOptions &read_options, ColumnFamilyData *cfd, SuperVersion *super_version, Arena *arena, SequenceNumber sequence, bool allow_unprepared_value, ArenaWrappedDBIter *db_iter=nullptr)
 
LogsWithPrepTrackerlogs_with_prep_tracker ()
 
BGJobLimits GetBGJobLimits () const
 
void ScheduleBgLogWriterClose (JobContext *job_context)
 
uint64_t MinLogNumberToKeep ()
 
uint64_t MinLogNumberToRecycle ()
 
uint64_t MinObsoleteSstNumberToKeep ()
 
uint64_t GetObsoleteSstFilesSize ()
 
uint64_t MinOptionsFileNumberToKeep ()
 
void FindObsoleteFiles (JobContext *job_context, bool force, bool no_full_scan=false)
 
void PurgeObsoleteFiles (JobContext &background_contet, bool schedule_only=false)
 
void SchedulePurge ()
 
const SnapshotListsnapshots () const
 
void LoadSnapshots (std::vector< SequenceNumber > *snap_vector, SequenceNumber *oldest_write_conflict_snapshot, const SequenceNumber &max_seq) const
 
const ImmutableDBOptionsimmutable_db_options () const
 
void CancelAllBackgroundWork (bool wait)
 
SuperVersionGetAndRefSuperVersion (ColumnFamilyData *cfd)
 
SuperVersionGetAndRefSuperVersion (uint32_t column_family_id)
 
void CleanupSuperVersion (SuperVersion *sv)
 
void ReturnAndCleanupSuperVersion (ColumnFamilyData *cfd, SuperVersion *sv)
 
void ReturnAndCleanupSuperVersion (uint32_t colun_family_id, SuperVersion *sv)
 
ColumnFamilyHandleGetColumnFamilyHandle (uint32_t column_family_id)
 
std::unique_ptr< ColumnFamilyHandleGetColumnFamilyHandleUnlocked (uint32_t column_family_id)
 
int num_running_flushes ()
 
int num_running_compactions ()
 
const WriteControllerwrite_controller ()
 
bool allow_2pc () const
 
std::unordered_map< std::string, RecoveredTransaction * > recovered_transactions ()
 
RecoveredTransactionGetRecoveredTransaction (const std::string &name)
 
void InsertRecoveredTransaction (const uint64_t log, const std::string &name, WriteBatch *batch, SequenceNumber seq, size_t batch_cnt, bool unprepared_batch)
 
void DeleteRecoveredTransaction (const std::string &name)
 
void DeleteAllRecoveredTransactions ()
 
void AddToLogsToFreeQueue (log::Writer *log_writer)
 
void AddSuperVersionsToFreeQueue (SuperVersion *sv)
 
void SetSnapshotChecker (SnapshotChecker *snapshot_checker)
 
void GetSnapshotContext (JobContext *job_context, std::vector< SequenceNumber > *snapshot_seqs, SequenceNumber *earliest_write_conflict_snapshot, SnapshotChecker **snapshot_checker)
 
void SetRecoverableStatePreReleaseCallback (PreReleaseCallback *callback)
 
InstrumentedMutexmutex () const
 
Status NewDB (std::vector< std::string > *new_filenames)
 
bool FindStatsByTime (uint64_t start_time, uint64_t end_time, uint64_t *new_time, std::map< std::string, uint64_t > *stats_map)
 
Status TablesRangeTombstoneSummary (ColumnFamilyHandle *column_family, int max_entries_to_print, std::string *out_str)
 
VersionSetGetVersionSet () const
 
Status WaitForCompact (const WaitForCompactOptions &wait_for_compact_options) override
 
Status TEST_CompactRange (int level, const Slice *begin, const Slice *end, ColumnFamilyHandle *column_family=nullptr, bool disallow_trivial_move=false)
 
Status TEST_SwitchWAL ()
 
bool TEST_UnableToReleaseOldestLog ()
 
bool TEST_IsLogGettingFlushed ()
 
Status TEST_SwitchMemtable (ColumnFamilyData *cfd=nullptr)
 
Status TEST_FlushMemTable (bool wait=true, bool allow_write_stall=false, ColumnFamilyHandle *cfh=nullptr)
 
Status TEST_FlushMemTable (ColumnFamilyData *cfd, const FlushOptions &flush_opts)
 
Status TEST_AtomicFlushMemTables (const autovector< ColumnFamilyData * > &provided_candidate_cfds, const FlushOptions &flush_opts)
 
Status TEST_WaitForBackgroundWork ()
 
Status TEST_WaitForFlushMemTable (ColumnFamilyHandle *column_family=nullptr)
 
Status TEST_WaitForCompact ()
 
Status TEST_WaitForCompact (const WaitForCompactOptions &wait_for_compact_options)
 
Status TEST_WaitForPurge ()
 
Status TEST_GetBGError ()
 
bool TEST_IsRecoveryInProgress ()
 
uint64_t TEST_MaxNextLevelOverlappingBytes (ColumnFamilyHandle *column_family=nullptr)
 
uint64_t TEST_Current_Manifest_FileNo ()
 
uint64_t TEST_Current_Next_FileNo ()
 
uint64_t TEST_GetLevel0TotalSize ()
 
void TEST_GetFilesMetaData (ColumnFamilyHandle *column_family, std::vector< std::vector< FileMetaData > > *metadata, std::vector< std::shared_ptr< BlobFileMetaData > > *blob_metadata=nullptr)
 
void TEST_LockMutex ()
 
void TEST_UnlockMutex ()
 
InstrumentedMutexTEST_Mutex ()
 
void TEST_SignalAllBgCv ()
 
void * TEST_BeginWrite ()
 
void TEST_EndWrite (void *w)
 
uint64_t TEST_MaxTotalInMemoryState () const
 
size_t TEST_LogsToFreeSize ()
 
uint64_t TEST_LogfileNumber ()
 
uint64_t TEST_total_log_size () const
 
void TEST_GetAllBlockCaches (std::unordered_set< const Cache * > *cache_set)
 
Status TEST_GetLatestMutableCFOptions (ColumnFamilyHandle *column_family, MutableCFOptions *mutable_cf_options)
 
CacheTEST_table_cache ()
 
WriteControllerTEST_write_controler ()
 
uint64_t TEST_FindMinLogContainingOutstandingPrep ()
 
uint64_t TEST_FindMinPrepLogReferencedByMemTable ()
 
size_t TEST_PreparedSectionCompletedSize ()
 
size_t TEST_LogsWithPrepSize ()
 
int TEST_BGCompactionsAllowed () const
 
int TEST_BGFlushesAllowed () const
 
size_t TEST_GetWalPreallocateBlockSize (uint64_t write_buffer_size) const
 
void TEST_WaitForPeriodicTaskRun (std::function< void()> callback) const
 
SeqnoToTimeMapping TEST_GetSeqnoToTimeMapping () const
 
const autovector< uint64_t > & TEST_GetFilesToQuarantine () const
 
size_t TEST_EstimateInMemoryStatsHistorySize () const
 
uint64_t TEST_GetCurrentLogNumber () const
 
void TEST_DeleteObsoleteFiles ()
 
const std::unordered_set< uint64_t > & TEST_GetFilesGrabbedForPurge () const
 
const PeriodicTaskSchedulerTEST_GetPeriodicTaskScheduler () const
 
void TEST_VerifyNoObsoleteFilesCached (bool db_mutex_already_held) const
 
void PersistStats ()
 
void DumpStats ()
 
void FlushInfoLog ()
 
void RecordSeqnoToTimeMapping (uint64_t populate_historical_seconds)
 
void InstallSeqnoToTimeMappingInSV (std::vector< SuperVersionContext > *sv_contexts)
 
bool seq_per_batch () const
 
virtual Status Put (const WriteOptions &options, const Slice &key, const Slice &value)
 
virtual Status Put (const WriteOptions &options, const Slice &key, const Slice &ts, const Slice &value)
 
virtual Status Merge (const WriteOptions &options, const Slice &key, const Slice &value)
 
virtual Status Delete (const WriteOptions &options, const Slice &key)
 
virtual Status Delete (const WriteOptions &options, const Slice &key, const Slice &ts)
 
virtual Status SingleDelete (const WriteOptions &options, const Slice &key)
 
virtual Status SingleDelete (const WriteOptions &options, const Slice &key, const Slice &ts)
 
virtual Status DeleteRange (const WriteOptions &options, const Slice &begin_key, const Slice &end_key)
 
virtual Status DeleteRange (const WriteOptions &options, const Slice &begin_key, const Slice &end_key, const Slice &ts)
 
virtual Status Get (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, std::string *value, std::string *timestamp) final
 
virtual Status Get (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *value) final
 
virtual Status Get (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, std::string *value) final
 
virtual Status Get (const ReadOptions &options, const Slice &key, std::string *value) final
 
virtual Status Get (const ReadOptions &options, const Slice &key, std::string *value, std::string *timestamp) final
 
virtual std::vector< StatusMultiGet (const ReadOptions &options, const std::vector< ColumnFamilyHandle * > &column_families, const std::vector< Slice > &keys, std::vector< std::string > *values, std::vector< std::string > *timestamps) final
 
virtual std::vector< StatusMultiGet (const ReadOptions &options, const std::vector< ColumnFamilyHandle * > &column_family, const std::vector< Slice > &keys, std::vector< std::string > *values) final
 
virtual std::vector< StatusMultiGet (const ReadOptions &options, const std::vector< Slice > &keys, std::vector< std::string > *values) final
 
virtual std::vector< StatusMultiGet (const ReadOptions &options, const std::vector< Slice > &keys, std::vector< std::string > *values, std::vector< std::string > *timestamps) final
 
virtual void MultiGet (const ReadOptions &options, ColumnFamilyHandle *column_family, const size_t num_keys, const Slice *keys, PinnableSlice *values, std::string *timestamps, Status *statuses, const bool sorted_input=false) final
 
virtual void MultiGet (const ReadOptions &options, ColumnFamilyHandle *column_family, const size_t num_keys, const Slice *keys, PinnableSlice *values, Status *statuses, const bool sorted_input=false) final
 
virtual void MultiGet (const ReadOptions &options, const size_t num_keys, ColumnFamilyHandle **column_families, const Slice *keys, PinnableSlice *values, Status *statuses, const bool sorted_input=false) final
 
virtual bool KeyMayExist (const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, std::string *value, bool *value_found=nullptr)
 
virtual bool KeyMayExist (const ReadOptions &options, const Slice &key, std::string *value, bool *value_found=nullptr)
 
virtual bool KeyMayExist (const ReadOptions &options, const Slice &key, std::string *value, std::string *timestamp, bool *value_found=nullptr)
 
virtual IteratorNewIterator (const ReadOptions &options)
 
virtual bool GetProperty (const Slice &property, std::string *value)
 
virtual bool GetMapProperty (const Slice &property, std::map< std::string, std::string > *value)
 
virtual bool GetIntProperty (const Slice &property, uint64_t *value)
 
virtual Status GetApproximateSizes (ColumnFamilyHandle *column_family, const Range *ranges, int n, uint64_t *sizes, SizeApproximationFlags include_flags=SizeApproximationFlags::INCLUDE_FILES)
 
virtual Status GetApproximateSizes (const Range *ranges, int n, uint64_t *sizes, SizeApproximationFlags include_flags=SizeApproximationFlags::INCLUDE_FILES)
 
virtual void GetApproximateMemTableStats (const Range &range, uint64_t *const count, uint64_t *const size)
 
virtual Status CompactRange (const CompactRangeOptions &options, const Slice *begin, const Slice *end)
 
virtual Status CompactFiles (const CompactionOptions &compact_options, const std::vector< std::string > &input_file_names, const int output_level, const int output_path_id=-1, std::vector< std::string > *const output_file_names=nullptr, CompactionJobInfo *compaction_job_info=nullptr)
 
virtual Status SetOptions (const std::unordered_map< std::string, std::string > &new_options)
 
virtual int NumberLevels ()
 
virtual int MaxMemCompactionLevel ()
 
virtual int Level0StopWriteTrigger ()
 
virtual Options GetOptions () const
 
virtual Status Flush (const FlushOptions &options)
 
virtual Status IngestExternalFile (const std::vector< std::string > &external_files, const IngestExternalFileOptions &options)
 
virtual Status CreateColumnFamilyWithImport (const ColumnFamilyOptions &options, const std::string &column_family_name, const ImportColumnFamilyOptions &import_options, const ExportImportFilesMetaData &metadata, ColumnFamilyHandle **handle)
 
virtual Status VerifyChecksum ()
 
virtual Status GetPropertiesOfAllTables (TablePropertiesCollection *props)
 
- ROCKSDB_NAMESPACE::DB(으)로부터 상속된 Public 멤버 함수
 DB ()
 
 DB (const DB &)=delete
 
void operator= (const DB &)=delete
 
virtual ~DB ()
 
virtual Status DestroyColumnFamilyHandle (ColumnFamilyHandle *column_family)
 
void GetColumnFamilyMetaData (ColumnFamilyMetaData *metadata)
 
virtual Status GetPropertiesOfTablesForLevels (ColumnFamilyHandle *, std::vector< std::unique_ptr< TablePropertiesCollection > > *)
 
virtual DBGetRootDB ()
 
virtual Status TryCatchUpWithPrimary ()
 

정적 Public 멤버 함수

static BGJobLimits GetBGJobLimits (int max_background_flushes, int max_background_compactions, int max_background_jobs, bool parallelize_compactions)
 
static Status Open (const DBOptions &db_options, const std::string &name, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles, DB **dbptr, const bool seq_per_batch, const bool batch_per_txn, const bool is_retry, bool *can_retry)
 
static IOStatus CreateAndNewDirectory (FileSystem *fs, const std::string &dirname, std::unique_ptr< FSDirectory > *directory)
 
static Status TEST_ValidateOptions (const DBOptions &db_options)
 
static void TEST_ResetDbSessionIdGen ()
 
static std::string GenerateDbSessionId (Env *env)
 
- ROCKSDB_NAMESPACE::DB(으)로부터 상속된 정적 Public 멤버 함수
static Status Open (const Options &options, const std::string &name, DB **dbptr)
 
static Status Open (const DBOptions &db_options, const std::string &name, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles, DB **dbptr)
 
static Status OpenForReadOnly (const Options &options, const std::string &name, DB **dbptr, bool error_if_wal_file_exists=false)
 
static Status OpenForReadOnly (const DBOptions &db_options, const std::string &name, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles, DB **dbptr, bool error_if_wal_file_exists=false)
 
static Status OpenAsSecondary (const Options &options, const std::string &name, const std::string &secondary_path, DB **dbptr)
 
static Status OpenAsSecondary (const DBOptions &db_options, const std::string &name, const std::string &secondary_path, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles, DB **dbptr)
 
static Status OpenAsFollower (const Options &options, const std::string &name, const std::string &leader_path, std::unique_ptr< DB > *dbptr)
 
static Status OpenAsFollower (const DBOptions &db_options, const std::string &name, const std::string &leader_path, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles, std::unique_ptr< DB > *dbptr)
 
static Status OpenAndCompact (const std::string &name, const std::string &output_directory, const std::string &input, std::string *output, const CompactionServiceOptionsOverride &override_options)
 
static Status OpenAndCompact (const OpenAndCompactOptions &options, const std::string &name, const std::string &output_directory, const std::string &input, std::string *output, const CompactionServiceOptionsOverride &override_options)
 
static Status OpenAndTrimHistory (const DBOptions &db_options, const std::string &dbname, const std::vector< ColumnFamilyDescriptor > &column_families, std::vector< ColumnFamilyHandle * > *handles, DB **dbptr, std::string trim_ts)
 
static Status ListColumnFamilies (const DBOptions &db_options, const std::string &name, std::vector< std::string > *column_families)
 

Protected 타입

enum  AssignOrder : bool { kDontAssignOrder , kDoAssignOrder }
 
enum  PublishLastSeq : bool { kDontPublishLastSeq , kDoPublishLastSeq }
 

Protected 멤버 함수

Status WriteOptionsFile (const WriteOptions &write_options, bool db_mutex_already_held)
 
Status CompactRangeInternal (const CompactRangeOptions &options, ColumnFamilyHandle *column_family, const Slice *begin, const Slice *end, const std::string &trim_ts)
 
Status RenameTempFileToOptionsFile (const std::string &file_name, bool is_remote_compaction_enabled)
 
Status DeleteObsoleteOptionsFiles ()
 
void NotifyOnManualFlushScheduled (autovector< ColumnFamilyData * > cfds, FlushReason flush_reason)
 
void NotifyOnFlushBegin (ColumnFamilyData *cfd, FileMetaData *file_meta, const MutableCFOptions &mutable_cf_options, int job_id, FlushReason flush_reason)
 
void NotifyOnFlushCompleted (ColumnFamilyData *cfd, const MutableCFOptions &mutable_cf_options, std::list< std::unique_ptr< FlushJobInfo > > *flush_jobs_info)
 
void NotifyOnCompactionBegin (ColumnFamilyData *cfd, Compaction *c, const Status &st, const CompactionJobStats &job_stats, int job_id)
 
void NotifyOnCompactionCompleted (ColumnFamilyData *cfd, Compaction *c, const Status &st, const CompactionJobStats &job_stats, int job_id)
 
void NotifyOnMemTableSealed (ColumnFamilyData *cfd, const MemTableInfo &mem_table_info)
 
void NotifyOnExternalFileIngested (ColumnFamilyData *cfd, const ExternalSstFileIngestionJob &ingestion_job)
 
Status FlushAllColumnFamilies (const FlushOptions &flush_options, FlushReason flush_reason)
 
virtual Status FlushForGetLiveFiles ()
 
void NewThreadStatusCfInfo (ColumnFamilyData *cfd) const
 
void EraseThreadStatusCfInfo (ColumnFamilyData *cfd) const
 
void EraseThreadStatusDbInfo () const
 
Status IngestWBWI (std::shared_ptr< WriteBatchWithIndex > wbwi, const WBWIMemTable::SeqnoRange &assigned_seqno, uint64_t min_prep_log, SequenceNumber last_seqno, bool memtable_updated, bool ignore_missing_cf)
 
Status WriteImpl (const WriteOptions &options, WriteBatch *updates, WriteCallback *callback=nullptr, UserWriteCallback *user_write_cb=nullptr, uint64_t *log_used=nullptr, uint64_t log_ref=0, bool disable_memtable=false, uint64_t *seq_used=nullptr, size_t batch_cnt=0, PreReleaseCallback *pre_release_callback=nullptr, PostMemTableCallback *post_memtable_callback=nullptr, std::shared_ptr< WriteBatchWithIndex > wbwi=nullptr, uint64_t min_prep_log=0)
 
Status PipelinedWriteImpl (const WriteOptions &options, WriteBatch *updates, WriteCallback *callback=nullptr, UserWriteCallback *user_write_cb=nullptr, uint64_t *log_used=nullptr, uint64_t log_ref=0, bool disable_memtable=false, uint64_t *seq_used=nullptr)
 
Status UnorderedWriteMemtable (const WriteOptions &write_options, WriteBatch *my_batch, WriteCallback *callback, uint64_t log_ref, SequenceNumber seq, const size_t sub_batch_cnt)
 
Status WriteImplWALOnly (WriteThread *write_thread, const WriteOptions &options, WriteBatch *updates, WriteCallback *callback, UserWriteCallback *user_write_cb, uint64_t *log_used, const uint64_t log_ref, uint64_t *seq_used, const size_t sub_batch_cnt, PreReleaseCallback *pre_release_callback, const AssignOrder assign_order, const PublishLastSeq publish_last_seq, const bool disable_memtable)
 
Status WriteRecoverableState ()
 
virtual Status CloseImpl ()
 
virtual Status Recover (const std::vector< ColumnFamilyDescriptor > &column_families, bool read_only=false, bool error_if_wal_file_exists=false, bool error_if_data_exists_in_wals=false, bool is_retry=false, uint64_t *recovered_seq=nullptr, RecoveryContext *recovery_ctx=nullptr, bool *can_retry=nullptr)
 
virtual bool OwnTablesAndLogs () const
 
Status SetupDBId (const WriteOptions &write_options, bool read_only, bool is_new_db, bool is_retry, VersionEdit *version_edit)
 
void SetDBId (std::string &&id, bool read_only, VersionEdit *version_edit)
 
std::set< std::string > CollectAllDBPaths ()
 
Status MaybeUpdateNextFileNumber (RecoveryContext *recovery_ctx)
 
void TrackExistingDataFiles (const std::vector< std::string > &existing_data_files)
 
void UntrackDataFiles ()
 
void SetDbSessionId ()
 
Status FailIfCfHasTs (const ColumnFamilyHandle *column_family) const
 
Status FailIfTsMismatchCf (ColumnFamilyHandle *column_family, const Slice &ts) const
 
Status FailIfReadCollapsedHistory (const ColumnFamilyData *cfd, const SuperVersion *sv, const Slice &ts) const
 
Status LogAndApplyForRecovery (const RecoveryContext &recovery_ctx)
 
void InvokeWalFilterIfNeededOnColumnFamilyToWalNumberMap ()
 
bool InvokeWalFilterIfNeededOnWalRecord (uint64_t wal_number, const std::string &wal_fname, log::Reader::Reporter &reporter, Status &status, bool &stop_replay, WriteBatch &batch)
 

Protected 속성

const std::string dbname_
 
std::string db_id_
 
std::string db_session_id_
 
std::unique_ptr< VersionSetversions_
 
bool own_info_log_
 
Status init_logger_creation_s_
 
const DBOptions initial_db_options_
 
Env *const env_
 
std::shared_ptr< IOTracerio_tracer_
 
const ImmutableDBOptions immutable_db_options_
 
FileSystemPtr fs_
 
MutableDBOptions mutable_db_options_
 
Statisticsstats_
 
std::unordered_map< std::string, RecoveredTransaction * > recovered_transactions_
 
std::unique_ptr< Tracertracer_
 
InstrumentedMutex trace_mutex_
 
BlockCacheTracer block_cache_tracer_
 
const std::atomic< bool > kManualCompactionCanceledFalse_ {false}
 
CacheAlignedInstrumentedMutex mutex_
 
ColumnFamilyHandleImpldefault_cf_handle_
 
InternalStatsdefault_cf_internal_stats_
 
std::shared_ptr< Cachetable_cache_
 
ErrorHandler error_handler_
 
EventLogger event_logger_
 
std::atomic< uint64_t > max_total_in_memory_state_
 
const FileOptions file_options_
 
FileOptions file_options_for_compaction_
 
std::unique_ptr< ColumnFamilyMemTablesImplcolumn_family_memtables_
 
const bool seq_per_batch_
 
const bool batch_per_txn_
 
std::atomic< int > next_job_id_
 
std::atomic< bool > shutting_down_
 
bool reject_new_background_jobs_
 

Private 타입

enum class  TaskType : uint8_t { kDefault = 0 , kManualCompaction = 1 , kCount = 2 }
 

Private 멤버 함수

Status InitPersistStatsColumnFamily ()
 
Status PersistentStatsProcessFormatVersion ()
 
Status ResumeImpl (DBRecoverContext context)
 
void MaybeIgnoreError (Status *s) const
 
const Status CreateArchivalDirectory ()
 
Status CreateColumnFamilyImpl (const ReadOptions &read_options, const WriteOptions &write_options, const ColumnFamilyOptions &cf_options, const std::string &cf_name, ColumnFamilyHandle **handle)
 
Status WrapUpCreateColumnFamilies (const ReadOptions &read_options, const WriteOptions &write_options, const std::vector< const ColumnFamilyOptions * > &cf_options)
 
Status DropColumnFamilyImpl (ColumnFamilyHandle *column_family)
 
void DeleteObsoleteFiles ()
 
void DeleteObsoleteFileImpl (int job_id, const std::string &fname, const std::string &path_to_sync, FileType type, uint64_t number)
 
std::list< uint64_t >::iterator CaptureCurrentFileNumberInPendingOutputs ()
 
void ReleaseFileNumberFromPendingOutputs (std::unique_ptr< std::list< uint64_t >::iterator > &v)
 
std::list< uint64_t >::iterator CaptureOptionsFileNumber ()
 
void ReleaseOptionsFileNumber (std::unique_ptr< std::list< uint64_t >::iterator > &v)
 
IOStatus SyncClosedWals (const WriteOptions &write_options, JobContext *job_context, VersionEdit *synced_wals, bool error_recovery_in_prog)
 
Status FlushMemTableToOutputFile (ColumnFamilyData *cfd, const MutableCFOptions &mutable_cf_options, bool *madeProgress, JobContext *job_context, FlushReason flush_reason, SuperVersionContext *superversion_context, std::vector< SequenceNumber > &snapshot_seqs, SequenceNumber earliest_write_conflict_snapshot, SnapshotChecker *snapshot_checker, LogBuffer *log_buffer, Env::Priority thread_pri)
 
Status FlushMemTablesToOutputFiles (const autovector< BGFlushArg > &bg_flush_args, bool *made_progress, JobContext *job_context, LogBuffer *log_buffer, Env::Priority thread_pri)
 
Status AtomicFlushMemTablesToOutputFiles (const autovector< BGFlushArg > &bg_flush_args, bool *made_progress, JobContext *job_context, LogBuffer *log_buffer, Env::Priority thread_pri)
 
Status RecoverLogFiles (const std::vector< uint64_t > &log_numbers, SequenceNumber *next_sequence, bool read_only, bool is_retry, bool *corrupted_log_found, RecoveryContext *recovery_ctx)
 
Status WriteLevel0TableForRecovery (int job_id, ColumnFamilyData *cfd, MemTable *mem, VersionEdit *edit)
 
Status GetLogSizeAndMaybeTruncate (uint64_t wal_number, bool truncate, LogFileNumberSize *log)
 
Status RestoreAliveLogFiles (const std::vector< uint64_t > &log_numbers)
 
Status DelayWrite (uint64_t num_bytes, WriteThread &write_thread, const WriteOptions &write_options)
 
void WriteBufferManagerStallWrites ()
 
Status ThrottleLowPriWritesIfNeeded (const WriteOptions &write_options, WriteBatch *my_batch)
 
Status ScheduleFlushes (WriteContext *context)
 
void MaybeFlushStatsCF (autovector< ColumnFamilyData * > *cfds)
 
Status TrimMemtableHistory (WriteContext *context)
 
Status SwitchMemtable (ColumnFamilyData *cfd, WriteContext *context, ReadOnlyMemTable *new_imm=nullptr, SequenceNumber last_seqno=0)
 
void SelectColumnFamiliesForAtomicFlush (autovector< ColumnFamilyData * > *selected_cfds, const autovector< ColumnFamilyData * > &provided_candidate_cfds={}, FlushReason flush_reason=FlushReason::kOthers)
 
Status FlushMemTable (ColumnFamilyData *cfd, const FlushOptions &options, FlushReason flush_reason, bool entered_write_thread=false)
 
Status AtomicFlushMemTables (const FlushOptions &options, FlushReason flush_reason, const autovector< ColumnFamilyData * > &provided_candidate_cfds={}, bool entered_write_thread=false)
 
Status RetryFlushesForErrorRecovery (FlushReason flush_reason, bool wait)
 
Status WaitUntilFlushWouldNotStallWrites (ColumnFamilyData *cfd, bool *flush_needed)
 
Status WaitForFlushMemTable (ColumnFamilyData *cfd, const uint64_t *flush_memtable_id=nullptr, bool resuming_from_bg_err=false, std::optional< FlushReason > flush_reason=std::nullopt)
 
Status WaitForFlushMemTables (const autovector< ColumnFamilyData * > &cfds, const autovector< const uint64_t * > &flush_memtable_ids, bool resuming_from_bg_err, std::optional< FlushReason > flush_reason)
 
void WaitForPendingWrites ()
 
void * GetTaskTag (TaskType type)
 
void * GetTaskTag (uint8_t type)
 
void AssignAtomicFlushSeq (const autovector< ColumnFamilyData * > &cfds)
 
Status SwitchWAL (WriteContext *write_context)
 
Status HandleWriteBufferManagerFlush (WriteContext *write_context)
 
Status PreprocessWrite (const WriteOptions &write_options, LogContext *log_context, WriteContext *write_context)
 
Status MergeBatch (const WriteThread::WriteGroup &write_group, WriteBatch *tmp_batch, WriteBatch **merged_batch, size_t *write_with_wal, WriteBatch **to_be_cached_state)
 
IOStatus WriteToWAL (const WriteBatch &merged_batch, const WriteOptions &write_options, log::Writer *log_writer, uint64_t *log_used, uint64_t *log_size, LogFileNumberSize &log_file_number_size)
 
IOStatus WriteToWAL (const WriteThread::WriteGroup &write_group, log::Writer *log_writer, uint64_t *log_used, bool need_log_sync, bool need_log_dir_sync, SequenceNumber sequence, LogFileNumberSize &log_file_number_size)
 
IOStatus ConcurrentWriteToWAL (const WriteThread::WriteGroup &write_group, uint64_t *log_used, SequenceNumber *last_sequence, size_t seq_inc)
 
void WriteStatusCheckOnLocked (const Status &status)
 
void WriteStatusCheck (const Status &status)
 
void WALIOStatusCheck (const IOStatus &status)
 
void MemTableInsertStatusCheck (const Status &memtable_insert_status)
 
Status CompactFilesImpl (const CompactionOptions &compact_options, ColumnFamilyData *cfd, Version *version, const std::vector< std::string > &input_file_names, std::vector< std::string > *const output_file_names, const int output_level, int output_path_id, JobContext *job_context, LogBuffer *log_buffer, CompactionJobInfo *compaction_job_info)
 
void TrackOrUntrackFiles (const std::vector< std::string > &existing_data_files, bool track)
 
void MaybeScheduleFlushOrCompaction ()
 
void GenerateFlushRequest (const autovector< ColumnFamilyData * > &cfds, FlushReason flush_reason, FlushRequest *req)
 
bool EnqueuePendingFlush (const FlushRequest &req)
 
void EnqueuePendingCompaction (ColumnFamilyData *cfd)
 
void SchedulePendingPurge (std::string fname, std::string dir_to_sync, FileType type, uint64_t number, int job_id)
 
void BackgroundCallCompaction (PrepickedCompaction *prepicked_compaction, Env::Priority thread_pri)
 
void BackgroundCallFlush (Env::Priority thread_pri)
 
void BackgroundCallPurge ()
 
Status BackgroundCompaction (bool *madeProgress, JobContext *job_context, LogBuffer *log_buffer, PrepickedCompaction *prepicked_compaction, Env::Priority thread_pri)
 
Status BackgroundFlush (bool *madeProgress, JobContext *job_context, LogBuffer *log_buffer, FlushReason *reason, bool *flush_rescheduled_to_retain_udt, Env::Priority thread_pri)
 
bool EnoughRoomForCompaction (ColumnFamilyData *cfd, const std::vector< CompactionInputFiles > &inputs, bool *sfm_bookkeeping, LogBuffer *log_buffer)
 
bool RequestCompactionToken (ColumnFamilyData *cfd, bool force, std::unique_ptr< TaskLimiterToken > *token, LogBuffer *log_buffer)
 
bool ShouldRescheduleFlushRequestToRetainUDT (const FlushRequest &flush_req)
 
Status StartPeriodicTaskScheduler ()
 
Status CancelPeriodicTaskScheduler ()
 
Status RegisterRecordSeqnoTimeWorker (const ReadOptions &read_options, const WriteOptions &write_options, bool is_new_db)
 
void PrintStatistics ()
 
size_t EstimateInMemoryStatsHistorySize () const
 
int FindMinimumEmptyLevelFitting (ColumnFamilyData *cfd, const MutableCFOptions &mutable_cf_options, int level)
 
Status ReFitLevel (ColumnFamilyData *cfd, int level, int target_level=-1)
 
void AddToCompactionQueue (ColumnFamilyData *cfd)
 
ColumnFamilyDataPopFirstFromCompactionQueue ()
 
FlushRequest PopFirstFromFlushQueue ()
 
ColumnFamilyDataPickCompactionFromQueue (std::unique_ptr< TaskLimiterToken > *token, LogBuffer *log_buffer)
 
IOStatus SyncWalImpl (bool include_current_wal, const WriteOptions &write_options, JobContext *job_context, VersionEdit *synced_wals, bool error_recovery_in_prog)
 
void MarkLogsSynced (uint64_t up_to, bool synced_dir, VersionEdit *edit)
 
Status ApplyWALToManifest (const ReadOptions &read_options, const WriteOptions &write_options, VersionEdit *edit)
 
void MarkLogsNotSynced (uint64_t up_to)
 
SnapshotImplGetSnapshotImpl (bool is_write_conflict_boundary, bool lock=true)
 
std::pair< Status, std::shared_ptr< const SnapshotImpl > > CreateTimestampedSnapshotImpl (SequenceNumber snapshot_seq, uint64_t ts, bool lock=true)
 
uint64_t GetMaxTotalWalSize () const
 
FSDirectoryGetDataDir (ColumnFamilyData *cfd, size_t path_id) const
 
Status MaybeReleaseTimestampedSnapshotsAndCheck ()
 
Status CloseHelper ()
 
void WaitForBackgroundWork ()
 
void InstallSuperVersionAndScheduleWork (ColumnFamilyData *cfd, SuperVersionContext *sv_context, const MutableCFOptions &mutable_cf_options)
 
bool GetIntPropertyInternal (ColumnFamilyData *cfd, const DBPropertyInfo &property_info, bool is_locked, uint64_t *value)
 
bool GetPropertyHandleOptionsStatistics (std::string *value)
 
bool HasPendingManualCompaction ()
 
bool HasExclusiveManualCompaction ()
 
void AddManualCompaction (ManualCompactionState *m)
 
void RemoveManualCompaction (ManualCompactionState *m)
 
bool ShouldntRunManualCompaction (ManualCompactionState *m)
 
bool HaveManualCompaction (ColumnFamilyData *cfd)
 
bool MCOverlap (ManualCompactionState *m, ManualCompactionState *m1)
 
void UpdateDeletionCompactionStats (const std::unique_ptr< Compaction > &c)
 
void BuildCompactionJobInfo (const ColumnFamilyData *cfd, Compaction *c, const Status &st, const CompactionJobStats &compaction_job_stats, const int job_id, CompactionJobInfo *compaction_job_info) const
 
Status ReserveFileNumbersBeforeIngestion (ColumnFamilyData *cfd, uint64_t num, std::unique_ptr< std::list< uint64_t >::iterator > &pending_output_elem, uint64_t *next_file_number)
 
bool ShouldPurge (uint64_t file_number) const
 
void MarkAsGrabbedForPurge (uint64_t file_number)
 
size_t GetWalPreallocateBlockSize (uint64_t write_buffer_size) const
 
Env::WriteLifeTimeHint CalculateWALWriteHint ()
 
IOStatus CreateWAL (const WriteOptions &write_options, uint64_t log_file_num, uint64_t recycle_log_number, size_t preallocate_block_size, log::Writer **new_log)
 
void PrepareMultiGetKeys (const size_t num_keys, bool sorted, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *key_ptrs)
 
void MultiGetCommon (const ReadOptions &options, ColumnFamilyHandle *column_family, const size_t num_keys, const Slice *keys, PinnableSlice *values, PinnableWideColumns *columns, std::string *timestamps, Status *statuses, bool sorted_input)
 
void MultiGetCommon (const ReadOptions &options, const size_t num_keys, ColumnFamilyHandle **column_families, const Slice *keys, PinnableSlice *values, PinnableWideColumns *columns, std::string *timestamps, Status *statuses, bool sorted_input)
 
template<class T, typename IterDerefFuncType>
Status MultiCFSnapshot (const ReadOptions &read_options, ReadCallback *callback, IterDerefFuncType iter_deref_func, T *cf_list, bool extra_sv_ref, SequenceNumber *snapshot, bool *sv_from_thread_local)
 
Status MultiGetImpl (const ReadOptions &read_options, size_t start_key, size_t num_keys, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *sorted_keys, SuperVersion *sv, SequenceNumber snap_seqnum, ReadCallback *callback)
 
void MultiGetWithCallbackImpl (const ReadOptions &read_options, ColumnFamilyHandle *column_family, ReadCallback *callback, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *sorted_keys)
 
Status DisableFileDeletionsWithLock ()
 
Status IncreaseFullHistoryTsLowImpl (ColumnFamilyData *cfd, std::string ts_low)
 
bool ShouldReferenceSuperVersion (const MergeContext &merge_context)
 
template<typename IterType, typename ImplType, typename ErrorIteratorFuncType>
std::unique_ptr< IterType > NewMultiCfIterator (const ReadOptions &_read_options, const std::vector< ColumnFamilyHandle * > &column_families, ErrorIteratorFuncType error_iterator_func)
 

정적 Private 멤버 함수

static bool IsRecoveryFlush (FlushReason flush_reason)
 
static void BGWorkCompaction (void *arg)
 
static void BGWorkBottomCompaction (void *arg)
 
static void BGWorkFlush (void *arg)
 
static void BGWorkPurge (void *arg)
 
static void UnscheduleCompactionCallback (void *arg)
 
static void UnscheduleFlushCallback (void *arg)
 
static Status ValidateOptions (const DBOptions &db_options)
 
static Status ValidateOptions (const DBOptions &db_options, const std::vector< ColumnFamilyDescriptor > &column_families)
 

Private 속성

FileLockdb_lock_
 
InstrumentedMutex options_mutex_
 
InstrumentedMutex stats_history_mutex_
 
InstrumentedMutex log_write_mutex_
 
std::atomic< int > manual_compaction_paused_
 
InstrumentedCondVar bg_cv_
 
uint64_t logfile_number_
 
std::deque< uint64_t > log_recycle_files_
 
uint64_t min_log_number_to_recycle_
 
bool log_dir_synced_
 
bool log_empty_
 
ColumnFamilyHandleImplpersist_stats_cf_handle_
 
bool persistent_stats_cfd_exists_ = true
 
std::deque< LogFileNumberSizealive_log_files_
 
std::deque< LogWriterNumberlogs_
 
InstrumentedCondVar log_sync_cv_
 
WriteBatch cached_recoverable_state_
 
std::atomic< bool > cached_recoverable_state_empty_ = {true}
 
std::atomic< uint64_t > total_log_size_
 
autovector< log::Writer * > logs_to_free_
 
bool is_snapshot_supported_
 
std::map< uint64_t, std::map< std::string, uint64_t > > stats_history_
 
std::map< std::string, uint64_t > stats_slice_
 
bool stats_slice_initialized_ = false
 
Directories directories_
 
WriteBufferManagerwrite_buffer_manager_
 
WriteThread write_thread_
 
WriteBatch tmp_batch_
 
WriteThread nonmem_write_thread_
 
WriteController write_controller_
 
uint64_t last_batch_group_size_
 
FlushScheduler flush_scheduler_
 
TrimHistoryScheduler trim_history_scheduler_
 
SnapshotList snapshots_
 
TimestampedSnapshotList timestamped_snapshots_
 
std::list< uint64_t > pending_outputs_
 
std::list< uint64_t > min_options_file_numbers_
 
std::deque< FlushRequestflush_queue_
 
std::deque< ColumnFamilyData * > compaction_queue_
 
std::unordered_map< uint64_t, PurgeFileInfopurge_files_
 
std::unordered_set< uint64_t > files_grabbed_for_purge_
 
std::deque< log::Writer * > logs_to_free_queue_
 
std::deque< SuperVersion * > superversions_to_free_queue_
 
int unscheduled_flushes_
 
int unscheduled_compactions_
 
int bg_bottom_compaction_scheduled_
 
int bg_compaction_scheduled_
 
int num_running_compactions_
 
int bg_flush_scheduled_
 
int num_running_flushes_
 
int bg_purge_scheduled_
 
std::deque< ManualCompactionState * > manual_compaction_dequeue_
 
int disable_delete_obsolete_files_
 
int pending_purge_obsolete_files_
 
uint64_t delete_obsolete_files_last_run_
 
std::condition_variable switch_cv_
 
std::mutex switch_mutex_
 
std::atomic< size_t > pending_memtable_writes_ = {}
 
std::atomic< bool > has_unpersisted_data_
 
bool unable_to_release_oldest_log_
 
int num_running_ingest_file_
 
WalManager wal_manager_
 
int bg_work_paused_
 
int bg_compaction_paused_
 
bool refitting_level_
 
bool opened_successfully_
 
SequenceNumber bottommost_files_mark_threshold_ = kMaxSequenceNumber
 
SequenceNumber standalone_range_deletion_files_mark_threshold_
 
LogsWithPrepTracker logs_with_prep_tracker_
 
std::unique_ptr< SnapshotCheckersnapshot_checker_
 
std::unique_ptr< PreReleaseCallbackrecoverable_state_pre_release_callback_
 
PeriodicTaskScheduler periodic_task_scheduler_
 
std::map< PeriodicTaskType, const PeriodicTaskFuncperiodic_task_functions_
 
const bool two_write_queues_
 
const bool manual_wal_flush_
 
const bool last_seq_same_as_publish_seq_
 
const bool use_custom_gc_
 
std::atomic< bool > shutdown_initiated_
 
bool own_sfm_
 
bool closed_
 
Status closing_status_
 
InstrumentedMutex closing_mutex_
 
InstrumentedCondVar atomic_flush_install_cv_
 
bool wal_in_db_path_
 
std::atomic< uint64_t > max_total_wal_size_
 
BlobFileCompletionCallback blob_callback_
 
std::unique_ptr< StallInterfacewbm_stall_
 
SeqnoToTimeMapping seqno_to_time_mapping_
 
std::unique_ptr< WriteControllerTokenlock_wal_write_token_
 
uint32_t lock_wal_count_
 

Friends

class DB
 
class ErrorHandler
 
class InternalStats
 
class PessimisticTransaction
 
class TransactionBaseImpl
 
class WriteCommittedTxn
 
class WritePreparedTxn
 
class WritePreparedTxnDB
 
class WriteBatchWithIndex
 
class WriteUnpreparedTxnDB
 
class WriteUnpreparedTxn
 
class ForwardIterator
 
struct SuperVersion
 
class CompactedDBImpl
 
class DBImplFollower
 
class DBTest_ConcurrentFlushWAL_Test
 
class DBTest_MixedSlowdownOptionsStop_Test
 
class DBCompactionTest_CompactBottomLevelFilesWithDeletions_Test
 
class DBCompactionTest_CompactionDuringShutdown_Test
 
class DBCompactionTest_DelayCompactBottomLevelFilesWithDeletions_Test
 
class DBCompactionTest_DisableCompactBottomLevelFiles_Test
 
class StatsHistoryTest_PersistentStatsCreateColumnFamilies_Test
 
class DBTest2_ReadCallbackTest_Test
 
class WriteCallbackPTest_WriteWithCallbackTest_Test
 
class XFTransactionWriteHandler
 
class DBBlobIndexTest
 
class WriteUnpreparedTransactionTest_RecoveryTest_Test
 
class CompactionServiceTest_PreservedOptionsLocalCompaction_Test
 
class CompactionServiceTest_PreservedOptionsRemoteCompaction_Test
 

추가로 상속된 멤버들

- ROCKSDB_NAMESPACE::DB(으)로부터 상속된 Public 타입
enum class  SizeApproximationFlags : uint8_t { NONE = 0 , INCLUDE_MEMTABLES = 1 << 0 , INCLUDE_FILES = 1 << 1 }
 

상세한 설명

db_impl.h 파일의 178 번째 라인에서 정의되었습니다.

멤버 열거형 문서화

◆ AssignOrder

enum ROCKSDB_NAMESPACE::DBImpl::AssignOrder : bool
protected
열거형 멤버
kDontAssignOrder 
kDoAssignOrder 

db_impl.h 파일의 1579 번째 라인에서 정의되었습니다.

◆ PublishLastSeq

enum ROCKSDB_NAMESPACE::DBImpl::PublishLastSeq : bool
protected
열거형 멤버
kDontPublishLastSeq 
kDoPublishLastSeq 

db_impl.h 파일의 1581 번째 라인에서 정의되었습니다.

◆ TaskType

enum class ROCKSDB_NAMESPACE::DBImpl::TaskType : uint8_t
strongprivate
열거형 멤버
kDefault 
kManualCompaction 
kCount 

db_impl.h 파일의 2185 번째 라인에서 정의되었습니다.

2185 : uint8_t {
2186 kDefault = 0,
2188 kCount = 2,
2189 };

생성자 & 소멸자 문서화

◆ DBImpl() [1/2]

ROCKSDB_NAMESPACE::DBImpl::DBImpl ( const DBOptions & options,
const std::string & dbname,
const bool seq_per_batch = false,
const bool batch_per_txn = true,
bool read_only = false )

db_impl.cc 파일의 166 번째 라인에서 정의되었습니다.

169 : dbname_(dbname),
170 own_info_log_(options.info_log == nullptr),
172 initial_db_options_(SanitizeOptions(dbname, options, read_only,
173 &init_logger_creation_s_)),
175 io_tracer_(std::make_shared<IOTracer>()),
176 immutable_db_options_(initial_db_options_),
177 fs_(immutable_db_options_.fs, io_tracer_),
178 mutable_db_options_(initial_db_options_),
180#ifdef COERCE_CONTEXT_SWITCH
181 mutex_(stats_, immutable_db_options_.clock, DB_MUTEX_WAIT_MICROS, &bg_cv_,
183#else // COERCE_CONTEXT_SWITCH
184 mutex_(stats_, immutable_db_options_.clock, DB_MUTEX_WAIT_MICROS,
186#endif // COERCE_CONTEXT_SWITCH
187 default_cf_handle_(nullptr),
188 error_handler_(this, immutable_db_options_, &mutex_),
191 file_options_(BuildDBOptions(immutable_db_options_, mutable_db_options_)),
192 file_options_for_compaction_(fs_->OptimizeForCompactionTableWrite(
193 file_options_, immutable_db_options_)),
194 seq_per_batch_(seq_per_batch),
195 batch_per_txn_(batch_per_txn),
196 next_job_id_(1),
197 shutting_down_(false),
199 db_lock_(nullptr),
201 bg_cv_(&mutex_),
203 log_dir_synced_(false),
204 log_empty_(true),
206 log_sync_cv_(&log_write_mutex_),
210 write_thread_(immutable_db_options_),
211 nonmem_write_thread_(immutable_db_options_),
228 wal_manager_(immutable_db_options_, file_options_, io_tracer_,
229 seq_per_batch),
232 refitting_level_(false),
235 two_write_queues_(options.two_write_queues),
236 manual_wal_flush_(options.manual_wal_flush),
237 // last_sequencee_ is always maintained by the main queue that also writes
238 // to the memtable. When two_write_queues_ is disabled last seq in
239 // memtable is the same as last seq published to the readers. When it is
240 // enabled but seq_per_batch_ is disabled, last seq in memtable still
241 // indicates last published seq since wal-only writes that go to the 2nd
242 // queue do not consume a sequence number. Otherwise writes performed by
243 // the 2nd queue could change what is visible to the readers. In this
244 // cases, last_seq_same_as_publish_seq_==false, the 2nd queue maintains a
245 // separate variable to indicate the last published sequence.
247 !(seq_per_batch && options.two_write_queues)),
248 // Since seq_per_batch_ is currently set only by WritePreparedTxn which
249 // requires a custom gc for compaction, we use that to set use_custom_gc_
250 // as well.
251 use_custom_gc_(seq_per_batch),
252 shutdown_initiated_(false),
253 own_sfm_(options.sst_file_manager == nullptr),
254 closed_(false),
257 &error_handler_, &event_logger_,
259 lock_wal_count_(0) {
260 // !batch_per_trx_ implies seq_per_batch_ because it is only unset for
261 // WriteUnprepared, which should use seq_per_batch_.
262 assert(batch_per_txn_ || seq_per_batch_);
263
264 // Reserve ten files or so for other uses and give the rest to TableCache.
265 // Give a large number for setting of "infinite" open files.
266 const int table_cache_size = (mutable_db_options_.max_open_files == -1)
267 ? TableCache::kInfiniteCapacity
268 : mutable_db_options_.max_open_files - 10;
269 LRUCacheOptions co;
270 co.capacity = table_cache_size;
272 co.metadata_charge_policy = kDontChargeCacheMetadata;
273 // TODO: Consider a non-fixed seed once test fallout (prefetch_test) is
274 // dealt with
275 co.hash_seed = 0;
278 assert(!db_session_id_.empty());
279
280 periodic_task_functions_.emplace(PeriodicTaskType::kDumpStats,
281 [this]() { this->DumpStats(); });
282 periodic_task_functions_.emplace(PeriodicTaskType::kPersistStats,
283 [this]() { this->PersistStats(); });
284 periodic_task_functions_.emplace(PeriodicTaskType::kFlushInfoLog,
285 [this]() { this->FlushInfoLog(); });
287 PeriodicTaskType::kRecordSeqnoTime, [this]() {
288 this->RecordSeqnoToTimeMapping(/*populate_historical_seconds=*/0);
289 });
290
291 versions_.reset(new VersionSet(
292 dbname_, &immutable_db_options_, file_options_, table_cache_.get(),
293 write_buffer_manager_, &write_controller_, &block_cache_tracer_,
294 io_tracer_, db_id_, db_session_id_, options.daily_offpeak_time_utc,
295 &error_handler_, read_only));
297 new ColumnFamilyMemTablesImpl(versions_->GetColumnFamilySet()));
298
300 DumpDBFileSummary(immutable_db_options_, dbname_, db_session_id_);
303 DumpSupportInfo(immutable_db_options_.info_log.get());
304
306 std::memory_order_relaxed);
307 if (write_buffer_manager_) {
308 wbm_stall_.reset(new WBMStallInterface());
309 }
310}
static char dbname[200]
Definition c_test.c:36
std::unique_ptr< StallInterface > wbm_stall_
Definition db_impl.h:3011
InstrumentedCondVar bg_cv_
Definition db_impl.h:2637
void RecordSeqnoToTimeMapping(uint64_t populate_historical_seconds)
Definition db_impl.cc:6804
ErrorHandler error_handler_
Definition db_impl.h:1382
std::atomic< uint64_t > max_total_wal_size_
Definition db_impl.h:3006
std::atomic< bool > shutdown_initiated_
Definition db_impl.h:2982
const std::string dbname_
Definition db_impl.h:1340
uint64_t last_batch_group_size_
Definition db_impl.h:2794
std::unique_ptr< VersionSet > versions_
Definition db_impl.h:1346
const bool last_seq_same_as_publish_seq_
Definition db_impl.h:2971
EventLogger event_logger_
Definition db_impl.h:1385
CacheAlignedInstrumentedMutex mutex_
Definition db_impl.h:1374
std::shared_ptr< IOTracer > io_tracer_
Definition db_impl.h:1352
WriteBufferManager * write_buffer_manager_
Definition db_impl.h:2780
InstrumentedCondVar atomic_flush_install_cv_
Definition db_impl.h:3003
std::atomic< bool > has_unpersisted_data_
Definition db_impl.h:2909
BlobFileCompletionCallback blob_callback_
Definition db_impl.h:3008
const bool manual_wal_flush_
Definition db_impl.h:2967
MutableDBOptions mutable_db_options_
Definition db_impl.h:1355
std::atomic< int > manual_compaction_paused_
Definition db_impl.h:2622
WriteThread write_thread_
Definition db_impl.h:2782
std::string db_session_id_
Definition db_impl.h:1345
std::atomic< bool > shutting_down_
Definition db_impl.h:1418
WriteThread nonmem_write_thread_
Definition db_impl.h:2786
FileOptions file_options_for_compaction_
Definition db_impl.h:1395
std::shared_ptr< Cache > table_cache_
Definition db_impl.h:1380
const ImmutableDBOptions immutable_db_options_
Definition db_impl.h:1353
std::atomic< int > next_job_id_
Definition db_impl.h:1416
ColumnFamilyHandleImpl * persist_stats_cf_handle_
Definition db_impl.h:2660
PeriodicTaskScheduler periodic_task_scheduler_
Definition db_impl.h:2959
std::unique_ptr< ColumnFamilyMemTablesImpl > column_family_memtables_
Definition db_impl.h:1397
std::atomic< uint64_t > total_log_size_
Definition db_impl.h:2764
ColumnFamilyHandleImpl * default_cf_handle_
Definition db_impl.h:1376
const bool two_write_queues_
Definition db_impl.h:2966
const DBOptions initial_db_options_
Definition db_impl.h:1350
InstrumentedCondVar log_sync_cv_
Definition db_impl.h:2754
const FileOptions file_options_
Definition db_impl.h:1392
WriteController write_controller_
Definition db_impl.h:2788
std::map< PeriodicTaskType, const PeriodicTaskFunc > periodic_task_functions_
Definition db_impl.h:2962
uint64_t delete_obsolete_files_last_run_
Definition db_impl.h:2896
std::atomic< uint64_t > max_total_in_memory_state_
Definition db_impl.h:1389
virtual uint64_t NowMicros()=0
std::shared_ptr< Cache > NewLRUCache(size_t capacity, int num_shard_bits=-1, bool strict_capacity_limit=false, double high_pri_pool_ratio=0.5, std::shared_ptr< MemoryAllocator > memory_allocator=nullptr, bool use_adaptive_mutex=kDefaultToAdaptiveMutex, CacheMetadataChargePolicy metadata_charge_policy=kDefaultCacheMetadataChargePolicy, double low_pri_pool_ratio=0.0)
Definition cache.h:270
void DumpRocksDBBuildVersion(Logger *log)
Definition db_impl.cc:5708
void DumpDBFileSummary(const ImmutableDBOptions &options, const std::string &dbname, const std::string &session_id)
ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions &db_options, const ColumnFamilyOptions &src)
DBOptions BuildDBOptions(const ImmutableDBOptions &immutable_db_options, const MutableDBOptions &mutable_db_options)
@ kDontChargeCacheMetadata
Definition cache.h:117
std::shared_ptr< Logger > info_log
Definition db_options.h:34
std::shared_ptr< SstFileManager > sst_file_manager
Definition db_options.h:33
std::vector< std::shared_ptr< EventListener > > listeners
Definition db_options.h:66
std::shared_ptr< FileSystem > fs
Definition db_options.h:113
std::shared_ptr< WriteBufferManager > write_buffer_manager
Definition db_options.h:63
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DBImpl() [2/2]

ROCKSDB_NAMESPACE::DBImpl::DBImpl ( const DBImpl & )
delete
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ ~DBImpl()

ROCKSDB_NAMESPACE::DBImpl::~DBImpl ( )
virtual

db_impl.cc 파일의 748 번째 라인에서 정의되었습니다.

748 {
749 ThreadStatus::OperationType cur_op_type =
750 ThreadStatusUtil::GetThreadOperation();
751 ThreadStatusUtil::SetThreadOperation(ThreadStatus::OperationType::OP_UNKNOWN);
752
753 // TODO: remove this.
755
756 InstrumentedMutexLock closing_lock_guard(&closing_mutex_);
757 if (!closed_) {
758 closed_ = true;
759
760 {
762 s.PermitUncheckedError();
763 }
764
767 }
768 ThreadStatusUtil::SetThreadOperation(cur_op_type);
769}
Status MaybeReleaseTimestampedSnapshotsAndCheck()
Definition db_impl.cc:520
virtual Status CloseImpl()
Definition db_impl.cc:746
void PermitUncheckedError() const
Definition status.h:67
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

멤버 함수 문서화

◆ AddManualCompaction()

void ROCKSDB_NAMESPACE::DBImpl::AddManualCompaction ( DBImpl::ManualCompactionState * m)
private

db_impl_compaction_flush.cc 파일의 4100 번째 라인에서 정의되었습니다.

4100 {
4101 assert(manual_compaction_paused_ == 0);
4102 manual_compaction_dequeue_.push_back(m);
4103}
std::deque< ManualCompactionState * > manual_compaction_dequeue_
Definition db_impl.h:2880
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AddSuperVersionsToFreeQueue()

void ROCKSDB_NAMESPACE::DBImpl::AddSuperVersionsToFreeQueue ( SuperVersion * sv)
inline

db_impl.h 파일의 1060 번째 라인에서 정의되었습니다.

1060 {
1061 superversions_to_free_queue_.push_back(sv);
1062 }
std::deque< SuperVersion * > superversions_to_free_queue_
Definition db_impl.h:2855
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AddToCompactionQueue()

void ROCKSDB_NAMESPACE::DBImpl::AddToCompactionQueue ( ColumnFamilyData * cfd)
private

db_impl_compaction_flush.cc 파일의 2964 번째 라인에서 정의되었습니다.

2964 {
2965 assert(!cfd->queued_for_compaction());
2966 cfd->Ref();
2967 compaction_queue_.push_back(cfd);
2968 cfd->set_queued_for_compaction(true);
2970}
std::deque< ColumnFamilyData * > compaction_queue_
Definition db_impl.h:2843
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AddToLogsToFreeQueue()

void ROCKSDB_NAMESPACE::DBImpl::AddToLogsToFreeQueue ( log::Writer * log_writer)
inline

db_impl.h 파일의 1055 번째 라인에서 정의되었습니다.

1055 {
1056 mutex_.AssertHeld();
1057 logs_to_free_queue_.push_back(log_writer);
1058 }
std::deque< log::Writer * > logs_to_free_queue_
Definition db_impl.h:2853
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ allow_2pc()

bool ROCKSDB_NAMESPACE::DBImpl::allow_2pc ( ) const
inline

db_impl.h 파일의 1001 번째 라인에서 정의되었습니다.

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ApplyWALToManifest()

Status ROCKSDB_NAMESPACE::DBImpl::ApplyWALToManifest ( const ReadOptions & read_options,
const WriteOptions & write_options,
VersionEdit * edit )
private

db_impl.cc 파일의 1750 번째 라인에서 정의되었습니다.

1752 {
1753 // not empty, write to MANIFEST.
1754 mutex_.AssertHeld();
1755
1756 Status status = versions_->LogAndApplyToDefaultColumnFamily(
1757 read_options, write_options, synced_wals, &mutex_,
1759 if (!status.ok() && versions_->io_status().IsIOError()) {
1760 error_handler_.SetBGError(versions_->io_status(),
1761 BackgroundErrorReason::kManifestWrite);
1762 }
1763 return status;
1764}
void SetBGError(const Status &bg_err, BackgroundErrorReason reason, bool wal_related=false)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AssignAtomicFlushSeq()

void ROCKSDB_NAMESPACE::DBImpl::AssignAtomicFlushSeq ( const autovector< ColumnFamilyData * > & cfds)
private

db_impl_write.cc 파일의 1885 번째 라인에서 정의되었습니다.

1885 {
1887 auto seq = versions_->LastSequence();
1888 for (auto cfd : cfds) {
1889 cfd->imm()->AssignAtomicFlushSeq(seq);
1890 }
1891}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AtomicFlushMemTables()

Status ROCKSDB_NAMESPACE::DBImpl::AtomicFlushMemTables ( const FlushOptions & options,
FlushReason flush_reason,
const autovector< ColumnFamilyData * > & provided_candidate_cfds = {},
bool entered_write_thread = false )
private

db_impl_compaction_flush.cc 파일의 2427 번째 라인에서 정의되었습니다.

2430 {
2432 if (!flush_options.wait && write_controller_.IsStopped()) {
2433 std::ostringstream oss;
2434 oss << "Writes have been stopped, thus unable to perform manual flush. "
2435 "Please try again later after writes are resumed";
2436 return Status::TryAgain(oss.str());
2437 }
2438 Status s;
2439 autovector<ColumnFamilyData*> candidate_cfds;
2440 if (provided_candidate_cfds.empty()) {
2441 // Generate candidate cfds if not provided
2442 {
2443 InstrumentedMutexLock l(&mutex_);
2444 for (ColumnFamilyData* cfd : *versions_->GetColumnFamilySet()) {
2445 if (!cfd->IsDropped() && cfd->initialized()) {
2446 cfd->Ref();
2447 candidate_cfds.push_back(cfd);
2448 }
2449 }
2450 }
2451 } else {
2452 candidate_cfds = provided_candidate_cfds;
2453 }
2454
2455 if (!flush_options.allow_write_stall) {
2456 int num_cfs_to_flush = 0;
2457 for (auto cfd : candidate_cfds) {
2458 bool flush_needed = true;
2459 s = WaitUntilFlushWouldNotStallWrites(cfd, &flush_needed);
2460 if (!s.ok()) {
2461 // Unref the newly generated candidate cfds (when not provided) in
2462 // `candidate_cfds`
2463 if (provided_candidate_cfds.empty()) {
2464 for (auto candidate_cfd : candidate_cfds) {
2465 candidate_cfd->UnrefAndTryDelete();
2466 }
2467 }
2468 return s;
2469 } else if (flush_needed) {
2470 ++num_cfs_to_flush;
2471 }
2472 }
2473 if (0 == num_cfs_to_flush) {
2474 // Unref the newly generated candidate cfds (when not provided) in
2475 // `candidate_cfds`
2476 if (provided_candidate_cfds.empty()) {
2477 for (auto candidate_cfd : candidate_cfds) {
2478 candidate_cfd->UnrefAndTryDelete();
2479 }
2480 }
2481 return s;
2482 }
2483 }
2484 const bool needs_to_join_write_thread = !entered_write_thread;
2485 FlushRequest flush_req;
2486 autovector<ColumnFamilyData*> cfds;
2487 {
2488 WriteContext context;
2489 InstrumentedMutexLock guard_lock(&mutex_);
2490
2491 WriteThread::Writer w;
2492 WriteThread::Writer nonmem_w;
2493 if (needs_to_join_write_thread) {
2494 write_thread_.EnterUnbatched(&w, &mutex_);
2495 if (two_write_queues_) {
2496 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
2497 }
2498 }
2500
2501 SelectColumnFamiliesForAtomicFlush(&cfds, candidate_cfds, flush_reason);
2502
2503 // Unref the newly generated candidate cfds (when not provided) in
2504 // `candidate_cfds`
2505 if (provided_candidate_cfds.empty()) {
2506 for (auto candidate_cfd : candidate_cfds) {
2507 candidate_cfd->UnrefAndTryDelete();
2508 }
2509 }
2510
2511 for (auto cfd : cfds) {
2512 if (cfd->mem()->IsEmpty() && cached_recoverable_state_empty_.load() &&
2513 !IsRecoveryFlush(flush_reason)) {
2514 continue;
2515 }
2516 cfd->Ref();
2517 s = SwitchMemtable(cfd, &context);
2518 cfd->UnrefAndTryDelete();
2519 if (!s.ok()) {
2520 break;
2521 }
2522 }
2523 if (s.ok()) {
2525 for (auto cfd : cfds) {
2526 cfd->imm()->FlushRequested();
2527 }
2528 // If the caller wants to wait for this flush to complete, it indicates
2529 // that the caller expects the ColumnFamilyData not to be free'ed by
2530 // other threads which may drop the column family concurrently.
2531 // Therefore, we increase the cfd's ref count.
2532 if (flush_options.wait) {
2533 for (auto cfd : cfds) {
2534 cfd->Ref();
2535 }
2536 }
2537 GenerateFlushRequest(cfds, flush_reason, &flush_req);
2538 EnqueuePendingFlush(flush_req);
2540 }
2541
2542 if (needs_to_join_write_thread) {
2544 if (two_write_queues_) {
2546 }
2547 }
2548 }
2549 NotifyOnManualFlushScheduled(cfds, flush_reason);
2550 TEST_SYNC_POINT("DBImpl::AtomicFlushMemTables:AfterScheduleFlush");
2551 TEST_SYNC_POINT("DBImpl::AtomicFlushMemTables:BeforeWaitForBgFlush");
2552 if (s.ok() && flush_options.wait) {
2553 autovector<const uint64_t*> flush_memtable_ids;
2554 for (auto& iter : flush_req.cfd_to_max_mem_id_to_persist) {
2555 flush_memtable_ids.push_back(&(iter.second));
2556 }
2558 cfds, flush_memtable_ids,
2559 flush_reason == FlushReason::kErrorRecovery /* resuming_from_bg_err */,
2560 flush_reason);
2561 InstrumentedMutexLock lock_guard(&mutex_);
2562 for (auto* cfd : cfds) {
2563 cfd->UnrefAndTryDelete();
2564 }
2565 }
2566 return s;
2567}
Status WaitForFlushMemTables(const autovector< ColumnFamilyData * > &cfds, const autovector< const uint64_t * > &flush_memtable_ids, bool resuming_from_bg_err, std::optional< FlushReason > flush_reason)
std::atomic< bool > cached_recoverable_state_empty_
Definition db_impl.h:2763
void AssignAtomicFlushSeq(const autovector< ColumnFamilyData * > &cfds)
void NotifyOnManualFlushScheduled(autovector< ColumnFamilyData * > cfds, FlushReason flush_reason)
static bool IsRecoveryFlush(FlushReason flush_reason)
Definition db_impl.h:1940
bool EnqueuePendingFlush(const FlushRequest &req)
void GenerateFlushRequest(const autovector< ColumnFamilyData * > &cfds, FlushReason flush_reason, FlushRequest *req)
Status WaitUntilFlushWouldNotStallWrites(ColumnFamilyData *cfd, bool *flush_needed)
void SelectColumnFamiliesForAtomicFlush(autovector< ColumnFamilyData * > *selected_cfds, const autovector< ColumnFamilyData * > &provided_candidate_cfds={}, FlushReason flush_reason=FlushReason::kOthers)
Status SwitchMemtable(ColumnFamilyData *cfd, WriteContext *context, ReadOnlyMemTable *new_imm=nullptr, SequenceNumber last_seqno=0)
void EnterUnbatched(Writer *w, InstrumentedMutex *mu)
#define TEST_SYNC_POINT(x)
Definition sync_point.h:159
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AtomicFlushMemTablesToOutputFiles()

Status ROCKSDB_NAMESPACE::DBImpl::AtomicFlushMemTablesToOutputFiles ( const autovector< BGFlushArg > & bg_flush_args,
bool * made_progress,
JobContext * job_context,
LogBuffer * log_buffer,
Env::Priority thread_pri )
private

db_impl_compaction_flush.cc 파일의 427 번째 라인에서 정의되었습니다.

429 {
430 mutex_.AssertHeld();
431 const ReadOptions read_options(Env::IOActivity::kFlush);
432 const WriteOptions write_options(Env::IOActivity::kFlush);
433
434 autovector<ColumnFamilyData*> cfds;
435 for (const auto& arg : bg_flush_args) {
436 cfds.emplace_back(arg.cfd_);
437 }
438
439#ifndef NDEBUG
440 for (const auto cfd : cfds) {
441 assert(cfd->imm()->NumNotFlushed() != 0);
442 assert(cfd->imm()->IsFlushPending());
443 }
444 for (const auto& bg_flush_arg : bg_flush_args) {
445 assert(bg_flush_arg.flush_reason_ == bg_flush_args[0].flush_reason_);
446 }
447#endif /* !NDEBUG */
448
449 std::vector<SequenceNumber> snapshot_seqs;
450 SequenceNumber earliest_write_conflict_snapshot;
451 SnapshotChecker* snapshot_checker;
452 GetSnapshotContext(job_context, &snapshot_seqs,
453 &earliest_write_conflict_snapshot, &snapshot_checker);
454
455 autovector<FSDirectory*> distinct_output_dirs;
456 autovector<std::string> distinct_output_dir_paths;
457 std::vector<std::unique_ptr<FlushJob>> jobs;
458 std::vector<MutableCFOptions> all_mutable_cf_options;
459 int num_cfs = static_cast<int>(cfds.size());
460 all_mutable_cf_options.reserve(num_cfs);
461 for (int i = 0; i < num_cfs; ++i) {
462 auto cfd = cfds[i];
463 FSDirectory* data_dir = GetDataDir(cfd, 0U);
464 const std::string& curr_path = cfd->ioptions()->cf_paths[0].path;
465
466 // Add to distinct output directories if eligible. Use linear search. Since
467 // the number of elements in the vector is not large, performance should be
468 // tolerable.
469 bool found = false;
470 for (const auto& path : distinct_output_dir_paths) {
471 if (path == curr_path) {
472 found = true;
473 break;
474 }
475 }
476 if (!found) {
477 distinct_output_dir_paths.emplace_back(curr_path);
478 distinct_output_dirs.emplace_back(data_dir);
479 }
480
481 all_mutable_cf_options.emplace_back(*cfd->GetLatestMutableCFOptions());
482 const MutableCFOptions& mutable_cf_options = all_mutable_cf_options.back();
483 uint64_t max_memtable_id = bg_flush_args[i].max_memtable_id_;
484 FlushReason flush_reason = bg_flush_args[i].flush_reason_;
485 jobs.emplace_back(new FlushJob(
486 dbname_, cfd, immutable_db_options_, mutable_cf_options,
487 max_memtable_id, file_options_for_compaction_, versions_.get(), &mutex_,
488 &shutting_down_, snapshot_seqs, earliest_write_conflict_snapshot,
489 snapshot_checker, job_context, flush_reason, log_buffer,
490 directories_.GetDbDir(), data_dir,
491 GetCompressionFlush(*cfd->ioptions(), mutable_cf_options), stats_,
492 &event_logger_, mutable_cf_options.report_bg_io_stats,
493 false /* sync_output_directory */, false /* write_manifest */,
494 thread_pri, io_tracer_,
495 cfd->GetSuperVersion()->ShareSeqnoToTimeMapping(), db_id_,
496 db_session_id_, cfd->GetFullHistoryTsLow(), &blob_callback_));
497 }
498
499 std::vector<FileMetaData> file_meta(num_cfs);
500 // Use of deque<bool> because vector<bool>
501 // is specific and doesn't allow &v[i].
502 std::deque<bool> switched_to_mempurge(num_cfs, false);
503 Status s;
504 IOStatus log_io_s = IOStatus::OK();
505 assert(num_cfs == static_cast<int>(jobs.size()));
506
507 for (int i = 0; i != num_cfs; ++i) {
508 const MutableCFOptions& mutable_cf_options = all_mutable_cf_options.at(i);
509 // may temporarily unlock and lock the mutex.
510 FlushReason flush_reason = bg_flush_args[i].flush_reason_;
511 NotifyOnFlushBegin(cfds[i], &file_meta[i], mutable_cf_options,
512 job_context->job_id, flush_reason);
513 }
514
515 if (logfile_number_ > 0) {
516 // TODO (yanqin) investigate whether we should sync the closed logs for
517 // single column family case.
518 VersionEdit synced_wals;
519 bool error_recovery_in_prog = error_handler_.IsRecoveryInProgress();
520 mutex_.Unlock();
521 log_io_s = SyncClosedWals(write_options, job_context, &synced_wals,
522 error_recovery_in_prog);
523 mutex_.Lock();
524 if (log_io_s.ok() && synced_wals.IsWalAddition()) {
525 log_io_s = status_to_io_status(
526 ApplyWALToManifest(read_options, write_options, &synced_wals));
527 }
528
529 if (!log_io_s.ok() && !log_io_s.IsShutdownInProgress() &&
530 !log_io_s.IsColumnFamilyDropped()) {
531 if (total_log_size_ > 0) {
532 error_handler_.SetBGError(log_io_s, BackgroundErrorReason::kFlush);
533 } else {
534 // If the WAL is empty, we use different error reason
535 error_handler_.SetBGError(log_io_s, BackgroundErrorReason::kFlushNoWAL);
536 }
537 }
538 }
539 s = log_io_s;
540
541 // exec_status stores the execution status of flush_jobs as
542 // <bool /* executed */, Status /* status code */>
543 autovector<std::pair<bool, Status>> exec_status;
544 std::vector<bool> pick_status;
545 for (int i = 0; i != num_cfs; ++i) {
546 // Initially all jobs are not executed, with status OK.
547 exec_status.emplace_back(false, Status::OK());
548 pick_status.push_back(false);
549 }
550
551 bool flush_for_recovery =
552 bg_flush_args[0].flush_reason_ == FlushReason::kErrorRecovery ||
553 bg_flush_args[0].flush_reason_ == FlushReason::kErrorRecoveryRetryFlush;
554 bool skip_set_bg_error = false;
555
556 if (s.ok() && !error_handler_.GetBGError().ok() &&
557 error_handler_.IsBGWorkStopped() && !flush_for_recovery) {
559 skip_set_bg_error = true;
560 assert(!s.ok());
561 ROCKS_LOG_BUFFER(log_buffer,
562 "[JOB %d] Skip flush due to background error %s",
563 job_context->job_id, s.ToString().c_str());
564 }
565
566 if (s.ok()) {
567 for (int i = 0; i != num_cfs; ++i) {
568 jobs[i]->PickMemTable();
569 pick_status[i] = true;
570 }
571 }
572
573 if (s.ok()) {
574 assert(switched_to_mempurge.size() ==
575 static_cast<long unsigned int>(num_cfs));
576 // TODO (yanqin): parallelize jobs with threads.
577 for (int i = 1; i != num_cfs; ++i) {
578 exec_status[i].second =
579 jobs[i]->Run(&logs_with_prep_tracker_, &file_meta[i],
580 &(switched_to_mempurge.at(i)));
581 exec_status[i].first = true;
582 }
583 if (num_cfs > 1) {
585 "DBImpl::AtomicFlushMemTablesToOutputFiles:SomeFlushJobsComplete:1");
587 "DBImpl::AtomicFlushMemTablesToOutputFiles:SomeFlushJobsComplete:2");
588 }
589 assert(exec_status.size() > 0);
590 assert(!file_meta.empty());
591 exec_status[0].second = jobs[0]->Run(
592 &logs_with_prep_tracker_, file_meta.data() /* &file_meta[0] */,
593 switched_to_mempurge.empty() ? nullptr : &(switched_to_mempurge.at(0)));
594 exec_status[0].first = true;
595
596 Status error_status;
597 for (const auto& e : exec_status) {
598 if (!e.second.ok()) {
599 s = e.second;
600 if (!e.second.IsShutdownInProgress() &&
601 !e.second.IsColumnFamilyDropped()) {
602 // If a flush job did not return OK, and the CF is not dropped, and
603 // the DB is not shutting down, then we have to return this result to
604 // caller later.
605 error_status = e.second;
606 }
607 }
608 }
609
610 s = error_status.ok() ? s : error_status;
611 }
612
613 if (s.IsColumnFamilyDropped()) {
614 s = Status::OK();
615 }
616
617 if (s.ok() || s.IsShutdownInProgress()) {
618 // Sync on all distinct output directories.
619 for (auto dir : distinct_output_dirs) {
620 if (dir != nullptr) {
621 IOOptions io_options;
622 Status error_status =
623 WritableFileWriter::PrepareIOOptions(write_options, io_options);
624 if (error_status.ok()) {
625 error_status = dir->FsyncWithDirOptions(
626 io_options, nullptr,
627 DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
628 }
629 if (!error_status.ok()) {
630 s = error_status;
631 break;
632 }
633 }
634 }
635 } else if (!skip_set_bg_error) {
636 // When `skip_set_bg_error` is true, no memtable is picked so
637 // there is no need to call Cancel() or RollbackMemtableFlush().
638 //
639 // Need to undo atomic flush if something went wrong, i.e. s is not OK and
640 // it is not because of CF drop.
641 // Have to cancel the flush jobs that have NOT executed because we need to
642 // unref the versions.
643 for (int i = 0; i != num_cfs; ++i) {
644 if (pick_status[i] && !exec_status[i].first) {
645 jobs[i]->Cancel();
646 }
647 }
648 for (int i = 0; i != num_cfs; ++i) {
649 if (exec_status[i].second.ok() && exec_status[i].first) {
650 auto& mems = jobs[i]->GetMemTables();
651 cfds[i]->imm()->RollbackMemtableFlush(
652 mems, /*rollback_succeeding_memtables=*/false);
653 }
654 }
655 }
656
657 if (s.ok()) {
658 const auto wait_to_install_func =
659 [&]() -> std::pair<Status, bool /*continue to wait*/> {
660 if (!versions_->io_status().ok()) {
661 // Something went wrong elsewhere, we cannot count on waiting for our
662 // turn to write/sync to MANIFEST or CURRENT. Just return.
663 return std::make_pair(versions_->io_status(), false);
664 } else if (shutting_down_.load(std::memory_order_acquire)) {
665 return std::make_pair(Status::ShutdownInProgress(), false);
666 }
667 bool ready = true;
668 for (size_t i = 0; i != cfds.size(); ++i) {
669 const auto& mems = jobs[i]->GetMemTables();
670 if (cfds[i]->IsDropped()) {
671 // If the column family is dropped, then do not wait.
672 continue;
673 } else if (!mems.empty() &&
674 cfds[i]->imm()->GetEarliestMemTableID() < mems[0]->GetID()) {
675 // If a flush job needs to install the flush result for mems and
676 // mems[0] is not the earliest memtable, it means another thread must
677 // be installing flush results for the same column family, then the
678 // current thread needs to wait.
679 ready = false;
680 break;
681 } else if (mems.empty() && cfds[i]->imm()->GetEarliestMemTableID() <=
682 bg_flush_args[i].max_memtable_id_) {
683 // If a flush job does not need to install flush results, then it has
684 // to wait until all memtables up to max_memtable_id_ (inclusive) are
685 // installed.
686 ready = false;
687 break;
688 }
689 }
690 return std::make_pair(Status::OK(), !ready);
691 };
692
693 bool resuming_from_bg_err =
694 error_handler_.IsDBStopped() || flush_for_recovery;
695 while ((!resuming_from_bg_err || error_handler_.GetRecoveryError().ok())) {
696 std::pair<Status, bool> res = wait_to_install_func();
697
699 "DBImpl::AtomicFlushMemTablesToOutputFiles:WaitToCommit", &res);
700
701 if (!res.first.ok()) {
702 s = res.first;
703 break;
704 } else if (!res.second) {
705 // we are the oldest immutable memtable
706 break;
707 }
708 // We are not the oldest immutable memtable
710 "DBImpl::AtomicFlushMemTablesToOutputFiles:WaitCV", &res);
711 //
712 // If bg work is stopped, recovery thread first calls
713 // WaitForBackgroundWork() before proceeding to flush for recovery. This
714 // flush can block WaitForBackgroundWork() while waiting for recovery
715 // flush to install result. To avoid this deadlock, we should abort here
716 // if there is background error.
717 if (!flush_for_recovery && error_handler_.IsBGWorkStopped() &&
720 assert(!s.ok());
721 break;
722 }
724
725 resuming_from_bg_err = error_handler_.IsDBStopped() || flush_for_recovery;
726 }
727
728 if (!resuming_from_bg_err) {
729 // If not resuming from bg err, then we determine future action based on
730 // whether we hit background error.
731 if (s.ok()) {
733 }
734 } else if (s.ok()) {
735 // If resuming from bg err, we still rely on wait_to_install_func()'s
736 // result to determine future action. If wait_to_install_func() returns
737 // non-ok already, then we should not proceed to flush result
738 // installation.
740 }
741 // Since we are not installing these memtables, need to rollback
742 // to allow future flush job to pick up these memtables.
743 if (!s.ok()) {
744 for (int i = 0; i != num_cfs; ++i) {
745 assert(exec_status[i].first);
746 assert(exec_status[i].second.ok());
747 auto& mems = jobs[i]->GetMemTables();
748 cfds[i]->imm()->RollbackMemtableFlush(
749 mems, /*rollback_succeeding_memtables=*/false);
750 }
751 }
752 }
753
754 if (s.ok()) {
755 autovector<ColumnFamilyData*> tmp_cfds;
756 autovector<const autovector<ReadOnlyMemTable*>*> mems_list;
757 autovector<const MutableCFOptions*> mutable_cf_options_list;
758 autovector<FileMetaData*> tmp_file_meta;
759 autovector<std::list<std::unique_ptr<FlushJobInfo>>*>
760 committed_flush_jobs_info;
761 for (int i = 0; i != num_cfs; ++i) {
762 const auto& mems = jobs[i]->GetMemTables();
763 if (!cfds[i]->IsDropped() && !mems.empty()) {
764 tmp_cfds.emplace_back(cfds[i]);
765 mems_list.emplace_back(&mems);
766 mutable_cf_options_list.emplace_back(&all_mutable_cf_options[i]);
767 tmp_file_meta.emplace_back(&file_meta[i]);
768 committed_flush_jobs_info.emplace_back(
769 jobs[i]->GetCommittedFlushJobsInfo());
770 }
771 }
772
774 nullptr /* imm_lists */, tmp_cfds, mutable_cf_options_list, mems_list,
775 versions_.get(), &logs_with_prep_tracker_, &mutex_, tmp_file_meta,
776 committed_flush_jobs_info, &job_context->memtables_to_free,
777 directories_.GetDbDir(), log_buffer);
778 }
779
780 if (s.ok()) {
781 assert(num_cfs ==
782 static_cast<int>(job_context->superversion_contexts.size()));
783 for (int i = 0; i != num_cfs; ++i) {
784 assert(cfds[i]);
785
786 if (cfds[i]->IsDropped()) {
787 continue;
788 }
790 &job_context->superversion_contexts[i],
791 all_mutable_cf_options[i]);
792
793 const std::string& column_family_name = cfds[i]->GetName();
794
795 Version* const current = cfds[i]->current();
796 assert(current);
797
798 const VersionStorageInfo* const storage_info = current->storage_info();
799 assert(storage_info);
800
801 VersionStorageInfo::LevelSummaryStorage tmp;
802 ROCKS_LOG_BUFFER(log_buffer, "[%s] Level summary: %s\n",
803 column_family_name.c_str(),
804 storage_info->LevelSummary(&tmp));
805
806 const auto& blob_files = storage_info->GetBlobFiles();
807 if (!blob_files.empty()) {
808 assert(blob_files.front());
809 assert(blob_files.back());
810
812 log_buffer,
813 "[%s] Blob file summary: head=%" PRIu64 ", tail=%" PRIu64 "\n",
814 column_family_name.c_str(), blob_files.front()->GetBlobFileNumber(),
815 blob_files.back()->GetBlobFileNumber());
816 }
817 }
818 if (made_progress) {
819 *made_progress = true;
820 }
821 auto sfm = static_cast<SstFileManagerImpl*>(
823 assert(all_mutable_cf_options.size() == static_cast<size_t>(num_cfs));
824 for (int i = 0; s.ok() && i != num_cfs; ++i) {
825 // If mempurge happened instead of Flush,
826 // no NotifyOnFlushCompleted call (no SST file created).
827 if (switched_to_mempurge[i]) {
828 continue;
829 }
830 if (cfds[i]->IsDropped()) {
831 continue;
832 }
833 NotifyOnFlushCompleted(cfds[i], all_mutable_cf_options[i],
834 jobs[i]->GetCommittedFlushJobsInfo());
835 if (sfm) {
836 std::string file_path = MakeTableFileName(
837 cfds[i]->ioptions()->cf_paths[0].path, file_meta[i].fd.GetNumber());
838 // TODO (PR7798). We should only add the file to the FileManager if it
839 // exists. Otherwise, some tests may fail. Ignore the error in the
840 // interim.
841 sfm->OnAddFile(file_path).PermitUncheckedError();
842 if (sfm->IsMaxAllowedSpaceReached() &&
844 Status new_bg_error =
845 Status::SpaceLimit("Max allowed space was reached");
846 error_handler_.SetBGError(new_bg_error,
847 BackgroundErrorReason::kFlush);
848 }
849 }
850 }
851 }
852
853 // Need to undo atomic flush if something went wrong, i.e. s is not OK and
854 // it is not because of CF drop.
855 if (!s.ok() && !s.IsColumnFamilyDropped() && !skip_set_bg_error) {
856 if (log_io_s.ok()) {
857 // Error while writing to MANIFEST.
858 // In fact, versions_->io_status() can also be the result of renaming
859 // CURRENT file. With current code, it's just difficult to tell. So just
860 // be pessimistic and try write to a new MANIFEST.
861 // TODO: distinguish between MANIFEST write and CURRENT renaming
862 if (!versions_->io_status().ok()) {
863 // If WAL sync is successful (either WAL size is 0 or there is no IO
864 // error), all the Manifest write will be map to soft error.
865 // TODO: kManifestWriteNoWAL and kFlushNoWAL are misleading. Refactor
866 // is needed.
868 BackgroundErrorReason::kManifestWriteNoWAL);
869 } else {
870 // If WAL sync is successful (either WAL size is 0 or there is no IO
871 // error), all the other SST file write errors will be set as
872 // kFlushNoWAL.
873 error_handler_.SetBGError(s, BackgroundErrorReason::kFlushNoWAL);
874 }
875 } else {
876 assert(s == log_io_s);
877 Status new_bg_error = s;
878 error_handler_.SetBGError(new_bg_error, BackgroundErrorReason::kFlush);
879 }
880 }
881
882 return s;
883}
Status ApplyWALToManifest(const ReadOptions &read_options, const WriteOptions &write_options, VersionEdit *edit)
Definition db_impl.cc:1750
void InstallSuperVersionAndScheduleWork(ColumnFamilyData *cfd, SuperVersionContext *sv_context, const MutableCFOptions &mutable_cf_options)
IOStatus SyncClosedWals(const WriteOptions &write_options, JobContext *job_context, VersionEdit *synced_wals, bool error_recovery_in_prog)
void NotifyOnFlushBegin(ColumnFamilyData *cfd, FileMetaData *file_meta, const MutableCFOptions &mutable_cf_options, int job_id, FlushReason flush_reason)
FSDirectory * GetDataDir(ColumnFamilyData *cfd, size_t path_id) const
Definition db_impl.cc:1263
void NotifyOnFlushCompleted(ColumnFamilyData *cfd, const MutableCFOptions &mutable_cf_options, std::list< std::unique_ptr< FlushJobInfo > > *flush_jobs_info)
void GetSnapshotContext(JobContext *job_context, std::vector< SequenceNumber > *snapshot_seqs, SequenceNumber *earliest_write_conflict_snapshot, SnapshotChecker **snapshot_checker)
#define ROCKS_LOG_BUFFER(LOG_BUF, FMT,...)
Definition logging.h:50
uint64_t SequenceNumber
Definition types.h:22
Status InstallMemtableAtomicFlushResults(const autovector< MemTableList * > *imm_lists, const autovector< ColumnFamilyData * > &cfds, const autovector< const MutableCFOptions * > &mutable_cf_options_list, const autovector< const autovector< ReadOnlyMemTable * > * > &mems_list, VersionSet *vset, LogsWithPrepTracker *prep_tracker, InstrumentedMutex *mu, const autovector< FileMetaData * > &file_metas, const autovector< std::list< std::unique_ptr< FlushJobInfo > > * > &committed_flush_jobs_info, autovector< ReadOnlyMemTable * > *to_delete, FSDirectory *db_directory, LogBuffer *log_buffer)
IOStatus status_to_io_status(Status &&status)
Definition io_status.h:237
std::string MakeTableFileName(const std::string &path, uint64_t number)
Definition filename.cc:112
CompressionType GetCompressionFlush(const ImmutableCFOptions &ioptions, const MutableCFOptions &mutable_cf_options)
Definition db_impl.cc:124
#define TEST_SYNC_POINT_CALLBACK(x, y)
Definition sync_point.h:164
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BackgroundCallCompaction()

void ROCKSDB_NAMESPACE::DBImpl::BackgroundCallCompaction ( PrepickedCompaction * prepicked_compaction,
Env::Priority thread_pri )
private

db_impl_compaction_flush.cc 파일의 3408 번째 라인에서 정의되었습니다.

3409 {
3410 bool made_progress = false;
3411 JobContext job_context(next_job_id_.fetch_add(1), true);
3412 TEST_SYNC_POINT("BackgroundCallCompaction:0");
3413 LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL,
3415 {
3416 InstrumentedMutexLock l(&mutex_);
3417
3419
3420 std::unique_ptr<std::list<uint64_t>::iterator>
3421 pending_outputs_inserted_elem(new std::list<uint64_t>::iterator(
3423
3424 assert((bg_thread_pri == Env::Priority::BOTTOM &&
3425 bg_bottom_compaction_scheduled_) ||
3426 (bg_thread_pri == Env::Priority::LOW && bg_compaction_scheduled_));
3427 Status s = BackgroundCompaction(&made_progress, &job_context, &log_buffer,
3428 prepicked_compaction, bg_thread_pri);
3429 TEST_SYNC_POINT("BackgroundCallCompaction:1");
3430 if (s.IsBusy()) {
3431 bg_cv_.SignalAll(); // In case a waiter can proceed despite the error
3432 mutex_.Unlock();
3434 10000); // prevent hot loop
3435 mutex_.Lock();
3436 } else if (!s.ok() && !s.IsShutdownInProgress() &&
3437 !s.IsManualCompactionPaused() && !s.IsColumnFamilyDropped()) {
3438 // Wait a little bit before retrying background compaction in
3439 // case this is an environmental problem and we do not want to
3440 // chew up resources for failed compactions for the duration of
3441 // the problem.
3442 uint64_t error_cnt =
3444 bg_cv_.SignalAll(); // In case a waiter can proceed despite the error
3445 mutex_.Unlock();
3446 log_buffer.FlushBufferToLog();
3448 "Waiting after background compaction error: %s, "
3449 "Accumulated background error counts: %" PRIu64,
3450 s.ToString().c_str(), error_cnt);
3453 mutex_.Lock();
3454 } else if (s.IsManualCompactionPaused()) {
3455 assert(prepicked_compaction);
3456 ManualCompactionState* m = prepicked_compaction->manual_compaction_state;
3457 assert(m);
3458 ROCKS_LOG_BUFFER(&log_buffer, "[%s] [JOB %d] Manual compaction paused",
3459 m->cfd->GetName().c_str(), job_context.job_id);
3460 }
3461
3462 ReleaseFileNumberFromPendingOutputs(pending_outputs_inserted_elem);
3463
3464 // If compaction failed, we want to delete all temporary files that we
3465 // might have created (they might not be all recorded in job_context in
3466 // case of a failure). Thus, we force full scan in FindObsoleteFiles()
3467 FindObsoleteFiles(&job_context, !s.ok() && !s.IsShutdownInProgress() &&
3468 !s.IsManualCompactionPaused() &&
3469 !s.IsColumnFamilyDropped() &&
3470 !s.IsBusy());
3471 TEST_SYNC_POINT("DBImpl::BackgroundCallCompaction:FoundObsoleteFiles");
3472
3473 // delete unnecessary files if any, this is done outside the mutex
3474 if (job_context.HaveSomethingToClean() ||
3475 job_context.HaveSomethingToDelete() || !log_buffer.IsEmpty()) {
3476 mutex_.Unlock();
3477 // Have to flush the info logs before bg_compaction_scheduled_--
3478 // because if bg_flush_scheduled_ becomes 0 and the lock is
3479 // released, the deconstructor of DB can kick in and destroy all the
3480 // states of DB so info_log might not be available after that point.
3481 // It also applies to access other states that DB owns.
3482 log_buffer.FlushBufferToLog();
3483 if (job_context.HaveSomethingToDelete()) {
3484 PurgeObsoleteFiles(job_context);
3485 TEST_SYNC_POINT("DBImpl::BackgroundCallCompaction:PurgedObsoleteFiles");
3486 }
3487 job_context.Clean();
3488 mutex_.Lock();
3489 }
3490
3491 assert(num_running_compactions_ > 0);
3493
3494 if (bg_thread_pri == Env::Priority::LOW) {
3496 } else {
3497 assert(bg_thread_pri == Env::Priority::BOTTOM);
3499 }
3500
3501 // See if there's more work to be done
3503
3504 if (prepicked_compaction != nullptr &&
3505 prepicked_compaction->task_token != nullptr) {
3506 // Releasing task tokens affects (and asserts on) the DB state, so
3507 // must be done before we potentially signal the DB close process to
3508 // proceed below.
3509 prepicked_compaction->task_token.reset();
3510 }
3511
3512 if (made_progress ||
3513 (bg_compaction_scheduled_ == 0 &&
3514 bg_bottom_compaction_scheduled_ == 0) ||
3515 HasPendingManualCompaction() || unscheduled_compactions_ == 0) {
3516 // signal if
3517 // * made_progress -- need to wakeup DelayWrite
3518 // * bg_{bottom,}_compaction_scheduled_ == 0 -- need to wakeup ~DBImpl
3519 // * HasPendingManualCompaction -- need to wakeup RunManualCompaction
3520 // If none of this is true, there is no need to signal since nobody is
3521 // waiting for it
3522 bg_cv_.SignalAll();
3523 }
3524 // IMPORTANT: there should be no code after calling SignalAll. This call may
3525 // signal the DB destructor that it's OK to proceed with destruction. In
3526 // that case, all DB variables will be dealloacated and referencing them
3527 // will cause trouble.
3528 }
3529}
void PurgeObsoleteFiles(JobContext &background_contet, bool schedule_only=false)
std::list< uint64_t >::iterator CaptureCurrentFileNumberInPendingOutputs()
Definition db_impl.cc:4830
void FindObsoleteFiles(JobContext *job_context, bool force, bool no_full_scan=false)
InternalStats * default_cf_internal_stats_
Definition db_impl.h:1377
void ReleaseFileNumberFromPendingOutputs(std::unique_ptr< std::list< uint64_t >::iterator > &v)
Definition db_impl.cc:4840
Status BackgroundCompaction(bool *madeProgress, JobContext *job_context, LogBuffer *log_buffer, PrepickedCompaction *prepicked_compaction, Env::Priority thread_pri)
virtual void SleepForMicroseconds(int micros)=0
#define ROCKS_LOG_ERROR(LGR, FMT,...)
Definition logging.h:44
void LogFlush(Logger *info_log)
Definition env.cc:858
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BackgroundCallFlush()

void ROCKSDB_NAMESPACE::DBImpl::BackgroundCallFlush ( Env::Priority thread_pri)
private

db_impl_compaction_flush.cc 파일의 3313 번째 라인에서 정의되었습니다.

3313 {
3314 bool made_progress = false;
3315 JobContext job_context(next_job_id_.fetch_add(1), true);
3316
3317 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCallFlush:start", nullptr);
3318
3319 LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL,
3321 TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:Start:1");
3322 TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:Start:2");
3323 {
3324 InstrumentedMutexLock l(&mutex_);
3325 assert(bg_flush_scheduled_);
3327
3328 std::unique_ptr<std::list<uint64_t>::iterator>
3329 pending_outputs_inserted_elem(new std::list<uint64_t>::iterator(
3331 FlushReason reason;
3332 bool flush_rescheduled_to_retain_udt = false;
3333 Status s =
3334 BackgroundFlush(&made_progress, &job_context, &log_buffer, &reason,
3335 &flush_rescheduled_to_retain_udt, thread_pri);
3336 if (s.IsTryAgain() && flush_rescheduled_to_retain_udt) {
3337 bg_cv_.SignalAll(); // In case a waiter can proceed despite the error
3338 mutex_.Unlock();
3339 TEST_SYNC_POINT_CALLBACK("DBImpl::AfterRetainUDTReschedule:cb", nullptr);
3341 100000); // prevent hot loop
3342 mutex_.Lock();
3343 } else if (!s.ok() && !s.IsShutdownInProgress() &&
3344 !s.IsColumnFamilyDropped() &&
3345 reason != FlushReason::kErrorRecovery) {
3346 // Wait a little bit before retrying background flush in
3347 // case this is an environmental problem and we do not want to
3348 // chew up resources for failed flushes for the duration of
3349 // the problem.
3350 uint64_t error_cnt =
3352 bg_cv_.SignalAll(); // In case a waiter can proceed despite the error
3353 mutex_.Unlock();
3355 "[JOB %d] Waiting after background flush error: %s, "
3356 "Accumulated background error counts: %" PRIu64,
3357 job_context.job_id, s.ToString().c_str(), error_cnt);
3358 log_buffer.FlushBufferToLog();
3361 mutex_.Lock();
3362 }
3363
3364 TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:FlushFinish:0");
3365 ReleaseFileNumberFromPendingOutputs(pending_outputs_inserted_elem);
3366 // There is no need to find obsolete files if the flush job is rescheduled
3367 // to retain user-defined timestamps because the job doesn't get to the
3368 // stage of actually flushing the MemTables.
3369 if (!flush_rescheduled_to_retain_udt) {
3370 // If flush failed, we want to delete all temporary files that we might
3371 // have created. Thus, we force full scan in FindObsoleteFiles()
3372 FindObsoleteFiles(&job_context, !s.ok() && !s.IsShutdownInProgress() &&
3373 !s.IsColumnFamilyDropped());
3374 }
3375 // delete unnecessary files if any, this is done outside the mutex
3376 if (job_context.HaveSomethingToClean() ||
3377 job_context.HaveSomethingToDelete() || !log_buffer.IsEmpty()) {
3378 mutex_.Unlock();
3379 TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:FilesFound");
3380 // Have to flush the info logs before bg_flush_scheduled_--
3381 // because if bg_flush_scheduled_ becomes 0 and the lock is
3382 // released, the deconstructor of DB can kick in and destroy all the
3383 // states of DB so info_log might not be available after that point.
3384 // It also applies to access other states that DB owns.
3385 log_buffer.FlushBufferToLog();
3386 if (job_context.HaveSomethingToDelete()) {
3387 PurgeObsoleteFiles(job_context);
3388 }
3389 job_context.Clean();
3390 mutex_.Lock();
3391 }
3392 TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:ContextCleanedUp");
3393
3394 assert(num_running_flushes_ > 0);
3397 // See if there's more work to be done
3400 bg_cv_.SignalAll();
3401 // IMPORTANT: there should be no code after calling SignalAll. This call may
3402 // signal the DB destructor that it's OK to proceed with destruction. In
3403 // that case, all DB variables will be dealloacated and referencing them
3404 // will cause trouble.
3405 }
3406}
Status BackgroundFlush(bool *madeProgress, JobContext *job_context, LogBuffer *log_buffer, FlushReason *reason, bool *flush_rescheduled_to_retain_udt, Env::Priority thread_pri)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BackgroundCallPurge()

void ROCKSDB_NAMESPACE::DBImpl::BackgroundCallPurge ( )
private

db_impl.cc 파일의 1963 번째 라인에서 정의되었습니다.

1963 {
1964 TEST_SYNC_POINT("DBImpl::BackgroundCallPurge:beforeMutexLock");
1965 mutex_.Lock();
1966
1967 while (!logs_to_free_queue_.empty()) {
1968 assert(!logs_to_free_queue_.empty());
1969 log::Writer* log_writer = *(logs_to_free_queue_.begin());
1970 logs_to_free_queue_.pop_front();
1971 mutex_.Unlock();
1972 delete log_writer;
1973 mutex_.Lock();
1974 }
1975 while (!superversions_to_free_queue_.empty()) {
1976 assert(!superversions_to_free_queue_.empty());
1978 superversions_to_free_queue_.pop_front();
1979 mutex_.Unlock();
1980 delete sv;
1981 mutex_.Lock();
1982 }
1983
1984 assert(bg_purge_scheduled_ > 0);
1985
1986 // Can't use iterator to go over purge_files_ because inside the loop we're
1987 // unlocking the mutex that protects purge_files_.
1988 while (!purge_files_.empty()) {
1989 auto it = purge_files_.begin();
1990 // Need to make a copy of the PurgeFilesInfo before unlocking the mutex.
1991 PurgeFileInfo purge_file = it->second;
1992
1993 const std::string& fname = purge_file.fname;
1994 const std::string& dir_to_sync = purge_file.dir_to_sync;
1995 FileType type = purge_file.type;
1996 uint64_t number = purge_file.number;
1997 int job_id = purge_file.job_id;
1998
1999 purge_files_.erase(it);
2000
2001 mutex_.Unlock();
2002 DeleteObsoleteFileImpl(job_id, fname, dir_to_sync, type, number);
2003 mutex_.Lock();
2004 }
2005
2007
2008 bg_cv_.SignalAll();
2009 // IMPORTANT:there should be no code after calling SignalAll. This call may
2010 // signal the DB destructor that it's OK to proceed with destruction. In
2011 // that case, all DB variables will be dealloacated and referencing them
2012 // will cause trouble.
2013 mutex_.Unlock();
2014}
void DeleteObsoleteFileImpl(int job_id, const std::string &fname, const std::string &path_to_sync, FileType type, uint64_t number)
friend struct SuperVersion
Definition db_impl.h:1717
std::unordered_map< uint64_t, PurgeFileInfo > purge_files_
Definition db_impl.h:2846
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BackgroundCompaction()

Status ROCKSDB_NAMESPACE::DBImpl::BackgroundCompaction ( bool * madeProgress,
JobContext * job_context,
LogBuffer * log_buffer,
PrepickedCompaction * prepicked_compaction,
Env::Priority thread_pri )
private

db_impl_compaction_flush.cc 파일의 3531 번째 라인에서 정의되었습니다.

3535 {
3536 ManualCompactionState* manual_compaction =
3537 prepicked_compaction == nullptr
3538 ? nullptr
3539 : prepicked_compaction->manual_compaction_state;
3540 *made_progress = false;
3541 mutex_.AssertHeld();
3542 TEST_SYNC_POINT("DBImpl::BackgroundCompaction:Start");
3543
3544 const ReadOptions read_options(Env::IOActivity::kCompaction);
3545 const WriteOptions write_options(Env::IOActivity::kCompaction);
3546
3547 bool is_manual = (manual_compaction != nullptr);
3548 std::unique_ptr<Compaction> c;
3549 if (prepicked_compaction != nullptr &&
3550 prepicked_compaction->compaction != nullptr) {
3551 c.reset(prepicked_compaction->compaction);
3552 }
3553 bool is_prepicked = is_manual || c;
3554
3555 // (manual_compaction->in_progress == false);
3556 bool trivial_move_disallowed =
3557 is_manual && manual_compaction->disallow_trivial_move;
3558
3559 CompactionJobStats compaction_job_stats;
3560 // Set is_remote_compaction to true on CompactionBegin Event if
3561 // compaction_service is set except for trivial moves. We do not know whether
3562 // remote compaction will actually be successfully scheduled, or fall back to
3563 // local at this time. CompactionCompleted event will tell the truth where
3564 // the compaction actually happened.
3565 compaction_job_stats.is_remote_compaction =
3567
3568 Status status;
3570 if (shutting_down_.load(std::memory_order_acquire)) {
3571 status = Status::ShutdownInProgress();
3572 } else if (is_manual &&
3573 manual_compaction->canceled.load(std::memory_order_acquire)) {
3574 status = Status::Incomplete(Status::SubCode::kManualCompactionPaused);
3575 }
3576 } else {
3577 status = error_handler_.GetBGError();
3578 // If we get here, it means a hard error happened after this compaction
3579 // was scheduled by MaybeScheduleFlushOrCompaction(), but before it got
3580 // a chance to execute. Since we didn't pop a cfd from the compaction
3581 // queue, increment unscheduled_compactions_
3583 }
3584
3585 if (!status.ok()) {
3586 if (is_manual) {
3587 manual_compaction->status = status;
3588 manual_compaction->done = true;
3589 manual_compaction->in_progress = false;
3590 manual_compaction = nullptr;
3591 }
3592 if (c) {
3593 c->ReleaseCompactionFiles(status);
3594 c.reset();
3595 }
3596 return status;
3597 }
3598
3599 if (is_manual) {
3600 // another thread cannot pick up the same work
3601 manual_compaction->in_progress = true;
3602 }
3603
3604 TEST_SYNC_POINT("DBImpl::BackgroundCompaction:InProgress");
3605
3606 std::unique_ptr<TaskLimiterToken> task_token;
3607
3608 bool sfm_reserved_compact_space = false;
3609 if (is_manual) {
3610 ManualCompactionState* m = manual_compaction;
3611 assert(m->in_progress);
3612 if (!c) {
3613 m->done = true;
3614 m->manual_end = nullptr;
3616 log_buffer,
3617 "[%s] Manual compaction from level-%d from %s .. "
3618 "%s; nothing to do\n",
3619 m->cfd->GetName().c_str(), m->input_level,
3620 (m->begin ? m->begin->DebugString(true).c_str() : "(begin)"),
3621 (m->end ? m->end->DebugString(true).c_str() : "(end)"));
3622 } else {
3623 // First check if we have enough room to do the compaction
3624 bool enough_room = EnoughRoomForCompaction(
3625 m->cfd, *(c->inputs()), &sfm_reserved_compact_space, log_buffer);
3626
3627 if (!enough_room) {
3628 // Then don't do the compaction
3629 c->ReleaseCompactionFiles(status);
3630 c.reset();
3631 // m's vars will get set properly at the end of this function,
3632 // as long as status == CompactionTooLarge
3633 status = Status::CompactionTooLarge();
3634 } else {
3636 log_buffer,
3637 "[%s] Manual compaction from level-%d to level-%d from %s .. "
3638 "%s; will stop at %s\n",
3639 m->cfd->GetName().c_str(), m->input_level, c->output_level(),
3640 (m->begin ? m->begin->DebugString(true).c_str() : "(begin)"),
3641 (m->end ? m->end->DebugString(true).c_str() : "(end)"),
3642 ((m->done || m->manual_end == nullptr)
3643 ? "(end)"
3644 : m->manual_end->DebugString(true).c_str()));
3645 }
3646 }
3647 } else if (!is_prepicked && !compaction_queue_.empty()) {
3649 // Can't compact right now, but try again later
3650 TEST_SYNC_POINT("DBImpl::BackgroundCompaction()::Conflict");
3651
3652 // Stay in the compaction queue.
3654
3655 return Status::OK();
3656 }
3657
3658 auto cfd = PickCompactionFromQueue(&task_token, log_buffer);
3659 if (cfd == nullptr) {
3660 // Can't find any executable task from the compaction queue.
3661 // All tasks have been throttled by compaction thread limiter.
3663 return Status::Busy();
3664 }
3665
3666 // We unreference here because the following code will take a Ref() on
3667 // this cfd if it is going to use it (Compaction class holds a
3668 // reference).
3669 // This will all happen under a mutex so we don't have to be afraid of
3670 // somebody else deleting it.
3671 if (cfd->UnrefAndTryDelete()) {
3672 // This was the last reference of the column family, so no need to
3673 // compact.
3674 return Status::OK();
3675 }
3676
3677 // Pick up latest mutable CF Options and use it throughout the
3678 // compaction job
3679 // Compaction makes a copy of the latest MutableCFOptions. It should be used
3680 // throughout the compaction procedure to make sure consistency. It will
3681 // eventually be installed into SuperVersion
3682 auto* mutable_cf_options = cfd->GetLatestMutableCFOptions();
3683 if (!mutable_cf_options->disable_auto_compactions && !cfd->IsDropped()) {
3684 // NOTE: try to avoid unnecessary copy of MutableCFOptions if
3685 // compaction is not necessary. Need to make sure mutex is held
3686 // until we make a copy in the following code
3687 TEST_SYNC_POINT("DBImpl::BackgroundCompaction():BeforePickCompaction");
3688 SnapshotChecker* snapshot_checker = nullptr;
3689 std::vector<SequenceNumber> snapshot_seqs;
3690 // This info is not useful for other scenarios, so save querying existing
3691 // snapshots for those cases.
3692 if (cfd->ioptions()->compaction_style == kCompactionStyleUniversal &&
3693 cfd->user_comparator()->timestamp_size() == 0) {
3694 SequenceNumber earliest_write_conflict_snapshot;
3695 GetSnapshotContext(job_context, &snapshot_seqs,
3696 &earliest_write_conflict_snapshot,
3697 &snapshot_checker);
3698 assert(is_snapshot_supported_ || snapshots_.empty());
3699 }
3700 c.reset(cfd->PickCompaction(*mutable_cf_options, mutable_db_options_,
3701 snapshot_seqs, snapshot_checker, log_buffer));
3702 TEST_SYNC_POINT("DBImpl::BackgroundCompaction():AfterPickCompaction");
3703
3704 if (c != nullptr) {
3705 bool enough_room = EnoughRoomForCompaction(
3706 cfd, *(c->inputs()), &sfm_reserved_compact_space, log_buffer);
3707
3708 if (!enough_room) {
3709 // Then don't do the compaction
3710 c->ReleaseCompactionFiles(status);
3711 c->column_family_data()
3712 ->current()
3713 ->storage_info()
3714 ->ComputeCompactionScore(*(c->immutable_options()),
3715 *(c->mutable_cf_options()));
3717
3718 c.reset();
3719 // Don't need to sleep here, because BackgroundCallCompaction
3720 // will sleep if !s.ok()
3721 status = Status::CompactionTooLarge();
3722 } else {
3723 // update statistics
3724 size_t num_files = 0;
3725 for (auto& each_level : *c->inputs()) {
3726 num_files += each_level.files.size();
3727 }
3728 RecordInHistogram(stats_, NUM_FILES_IN_SINGLE_COMPACTION, num_files);
3729
3730 // There are three things that can change compaction score:
3731 // 1) When flush or compaction finish. This case is covered by
3732 // InstallSuperVersionAndScheduleWork
3733 // 2) When MutableCFOptions changes. This case is also covered by
3734 // InstallSuperVersionAndScheduleWork, because this is when the new
3735 // options take effect.
3736 // 3) When we Pick a new compaction, we "remove" those files being
3737 // compacted from the calculation, which then influences compaction
3738 // score. Here we check if we need the new compaction even without the
3739 // files that are currently being compacted. If we need another
3740 // compaction, we might be able to execute it in parallel, so we add
3741 // it to the queue and schedule a new thread.
3742 if (cfd->NeedsCompaction()) {
3743 // Yes, we need more compactions!
3746 }
3747 }
3748 }
3749 }
3750 }
3751
3752 IOStatus io_s;
3753 bool compaction_released = false;
3754 if (!c) {
3755 // Nothing to do
3756 ROCKS_LOG_BUFFER(log_buffer, "Compaction nothing to do");
3757 } else if (c->deletion_compaction()) {
3758 // TODO(icanadi) Do we want to honor snapshots here? i.e. not delete old
3759 // file if there is alive snapshot pointing to it
3760 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:BeforeCompaction",
3761 c->column_family_data());
3762 assert(c->num_input_files(1) == 0);
3763 assert(c->column_family_data()->ioptions()->compaction_style ==
3764 kCompactionStyleFIFO);
3765
3766 compaction_job_stats.num_input_files = c->num_input_files(0);
3767
3768 NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
3769 compaction_job_stats, job_context->job_id);
3770
3771 for (const auto& f : *c->inputs(0)) {
3772 c->edit()->DeleteFile(c->level(), f->fd.GetNumber());
3773 }
3774 status = versions_->LogAndApply(
3775 c->column_family_data(), *c->mutable_cf_options(), read_options,
3776 write_options, c->edit(), &mutex_, directories_.GetDbDir(),
3777 /*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
3778 [&c, &compaction_released](const Status& s) {
3779 c->ReleaseCompactionFiles(s);
3780 compaction_released = true;
3781 });
3782 io_s = versions_->io_status();
3784 c->column_family_data(), job_context->superversion_contexts.data(),
3785 *c->mutable_cf_options());
3786 ROCKS_LOG_BUFFER(log_buffer, "[%s] Deleted %d files\n",
3787 c->column_family_data()->GetName().c_str(),
3788 c->num_input_files(0));
3789 if (status.ok() && io_s.ok()) {
3791 }
3792 *made_progress = true;
3793 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:AfterCompaction",
3794 c->column_family_data());
3795 } else if (!trivial_move_disallowed && c->IsTrivialMove()) {
3796 TEST_SYNC_POINT("DBImpl::BackgroundCompaction:TrivialMove");
3797 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:BeforeCompaction",
3798 c->column_family_data());
3799 // Instrument for event update
3800 // TODO(yhchiang): add op details for showing trivial-move.
3801 ThreadStatusUtil::SetColumnFamily(c->column_family_data());
3802 ThreadStatusUtil::SetThreadOperation(ThreadStatus::OP_COMPACTION);
3803
3804 compaction_job_stats.num_input_files = c->num_input_files(0);
3805 // Trivial moves do not get compacted remotely
3806 compaction_job_stats.is_remote_compaction = false;
3807
3808 NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
3809 compaction_job_stats, job_context->job_id);
3810
3811 // Move files to next level
3812 int32_t moved_files = 0;
3813 int64_t moved_bytes = 0;
3814 for (unsigned int l = 0; l < c->num_input_levels(); l++) {
3815 if (c->level(l) == c->output_level()) {
3816 continue;
3817 }
3818 for (size_t i = 0; i < c->num_input_files(l); i++) {
3819 FileMetaData* f = c->input(l, i);
3820 c->edit()->DeleteFile(c->level(l), f->fd.GetNumber());
3821 c->edit()->AddFile(
3822 c->output_level(), f->fd.GetNumber(), f->fd.GetPathId(),
3823 f->fd.GetFileSize(), f->smallest, f->largest, f->fd.smallest_seqno,
3824 f->fd.largest_seqno, f->marked_for_compaction, f->temperature,
3825 f->oldest_blob_file_number, f->oldest_ancester_time,
3826 f->file_creation_time, f->epoch_number, f->file_checksum,
3827 f->file_checksum_func_name, f->unique_id,
3828 f->compensated_range_deletion_size, f->tail_size,
3829 f->user_defined_timestamps_persisted);
3830
3832 log_buffer,
3833 "[%s] Moving #%" PRIu64 " to level-%d %" PRIu64 " bytes\n",
3834 c->column_family_data()->GetName().c_str(), f->fd.GetNumber(),
3835 c->output_level(), f->fd.GetFileSize());
3836 ++moved_files;
3837 moved_bytes += f->fd.GetFileSize();
3838 }
3839 }
3840 if (c->compaction_reason() == CompactionReason::kLevelMaxLevelSize &&
3841 c->immutable_options()->compaction_pri == kRoundRobin) {
3842 int start_level = c->start_level();
3843 if (start_level > 0) {
3844 auto vstorage = c->input_version()->storage_info();
3845 c->edit()->AddCompactCursor(
3846 start_level,
3847 vstorage->GetNextCompactCursor(start_level, c->num_input_files(0)));
3848 }
3849 }
3850 status = versions_->LogAndApply(
3851 c->column_family_data(), *c->mutable_cf_options(), read_options,
3852 write_options, c->edit(), &mutex_, directories_.GetDbDir(),
3853 /*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
3854 [&c, &compaction_released](const Status& s) {
3855 c->ReleaseCompactionFiles(s);
3856 compaction_released = true;
3857 });
3858 io_s = versions_->io_status();
3859 // Use latest MutableCFOptions
3861 c->column_family_data(), job_context->superversion_contexts.data(),
3862 *c->mutable_cf_options());
3863
3864 VersionStorageInfo::LevelSummaryStorage tmp;
3865 c->column_family_data()->internal_stats()->IncBytesMoved(c->output_level(),
3866 moved_bytes);
3867 {
3868 event_logger_.LogToBuffer(log_buffer)
3869 << "job" << job_context->job_id << "event"
3870 << "trivial_move"
3871 << "destination_level" << c->output_level() << "files" << moved_files
3872 << "total_files_size" << moved_bytes;
3873 }
3875 log_buffer,
3876 "[%s] Moved #%d files to level-%d %" PRIu64 " bytes %s: %s\n",
3877 c->column_family_data()->GetName().c_str(), moved_files,
3878 c->output_level(), moved_bytes, status.ToString().c_str(),
3879 c->column_family_data()->current()->storage_info()->LevelSummary(&tmp));
3880 *made_progress = true;
3881
3882 // Clear Instrument
3883 ThreadStatusUtil::ResetThreadStatus();
3884 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:AfterCompaction",
3885 c->column_family_data());
3886 } else if (!is_prepicked && c->output_level() > 0 &&
3887 c->output_level() ==
3888 c->column_family_data()
3889 ->current()
3890 ->storage_info()
3891 ->MaxOutputLevel(
3893 env_->GetBackgroundThreads(Env::Priority::BOTTOM) > 0) {
3894 // Forward compactions involving last level to the bottom pool if it exists,
3895 // such that compactions unlikely to contribute to write stalls can be
3896 // delayed or deprioritized.
3897 TEST_SYNC_POINT("DBImpl::BackgroundCompaction:ForwardToBottomPriPool");
3898 CompactionArg* ca = new CompactionArg;
3899 ca->db = this;
3900 ca->compaction_pri_ = Env::Priority::BOTTOM;
3901 ca->prepicked_compaction = new PrepickedCompaction;
3902 ca->prepicked_compaction->compaction = c.release();
3903 ca->prepicked_compaction->manual_compaction_state = nullptr;
3904 // Transfer requested token, so it doesn't need to do it again.
3905 ca->prepicked_compaction->task_token = std::move(task_token);
3907 assert(c == nullptr);
3908 env_->Schedule(&DBImpl::BGWorkBottomCompaction, ca, Env::Priority::BOTTOM,
3909 this, &DBImpl::UnscheduleCompactionCallback);
3910 } else {
3911 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:BeforeCompaction",
3912 c->column_family_data());
3913 int output_level __attribute__((__unused__));
3914 output_level = c->output_level();
3915 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:NonTrivial",
3916 &output_level);
3917 std::vector<SequenceNumber> snapshot_seqs;
3918 SequenceNumber earliest_write_conflict_snapshot;
3919 SnapshotChecker* snapshot_checker;
3920 GetSnapshotContext(job_context, &snapshot_seqs,
3921 &earliest_write_conflict_snapshot, &snapshot_checker);
3922 assert(is_snapshot_supported_ || snapshots_.empty());
3923
3924 CompactionJob compaction_job(
3925 job_context->job_id, c.get(), immutable_db_options_,
3926 mutable_db_options_, file_options_for_compaction_, versions_.get(),
3927 &shutting_down_, log_buffer, directories_.GetDbDir(),
3928 GetDataDir(c->column_family_data(), c->output_path_id()),
3929 GetDataDir(c->column_family_data(), 0), stats_, &mutex_,
3930 &error_handler_, snapshot_seqs, earliest_write_conflict_snapshot,
3931 snapshot_checker, job_context, table_cache_, &event_logger_,
3932 c->mutable_cf_options()->paranoid_file_checks,
3933 c->mutable_cf_options()->report_bg_io_stats, dbname_,
3934 &compaction_job_stats, thread_pri, io_tracer_,
3935 is_manual ? manual_compaction->canceled
3936 : kManualCompactionCanceledFalse_,
3937 db_id_, db_session_id_, c->column_family_data()->GetFullHistoryTsLow(),
3938 c->trim_ts(), &blob_callback_, &bg_compaction_scheduled_,
3939 &bg_bottom_compaction_scheduled_);
3940 compaction_job.Prepare();
3941
3942 std::unique_ptr<std::list<uint64_t>::iterator> min_options_file_number_elem;
3943 if (immutable_db_options().compaction_service != nullptr) {
3944 min_options_file_number_elem.reset(
3945 new std::list<uint64_t>::iterator(CaptureOptionsFileNumber()));
3946 }
3947
3948 NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
3949 compaction_job_stats, job_context->job_id);
3950 mutex_.Unlock();
3952 "DBImpl::BackgroundCompaction:NonTrivial:BeforeRun", nullptr);
3953 // Should handle error?
3954 compaction_job.Run().PermitUncheckedError();
3955 TEST_SYNC_POINT("DBImpl::BackgroundCompaction:NonTrivial:AfterRun");
3956 mutex_.Lock();
3957
3958 if (immutable_db_options().compaction_service != nullptr) {
3959 ReleaseOptionsFileNumber(min_options_file_number_elem);
3960 }
3961
3962 status =
3963 compaction_job.Install(*c->mutable_cf_options(), &compaction_released);
3964 io_s = compaction_job.io_status();
3965 if (status.ok()) {
3967 c->column_family_data(), job_context->superversion_contexts.data(),
3968 *c->mutable_cf_options());
3969 }
3970 *made_progress = true;
3971 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:AfterCompaction",
3972 c->column_family_data());
3973 }
3974
3975 if (status.ok() && !io_s.ok()) {
3976 status = io_s;
3977 } else {
3978 io_s.PermitUncheckedError();
3979 }
3980
3981 if (c != nullptr) {
3982 if (!compaction_released) {
3983 c->ReleaseCompactionFiles(status);
3984 } else {
3985#ifndef NDEBUG
3986 // Sanity checking that compaction files are freed.
3987 for (size_t i = 0; i < c->num_input_levels(); i++) {
3988 for (size_t j = 0; j < c->inputs(i)->size(); j++) {
3989 // When status is not OK, compaction's result installation failed and
3990 // no new Version installed. The files could have been released and
3991 // picked up again by other compaction attempts.
3992 assert(!c->input(i, j)->being_compacted || !status.ok());
3993 }
3994 }
3995 std::unordered_set<Compaction*>* cip = c->column_family_data()
3996 ->compaction_picker()
3997 ->compactions_in_progress();
3998 assert(cip->find(c.get()) == cip->end());
3999#endif
4000 }
4001
4002 *made_progress = true;
4003
4004 // Need to make sure SstFileManager does its bookkeeping
4005 auto sfm = static_cast<SstFileManagerImpl*>(
4007 if (sfm && sfm_reserved_compact_space) {
4008 sfm->OnCompactionCompletion(c.get());
4009 }
4010
4011 NotifyOnCompactionCompleted(c->column_family_data(), c.get(), status,
4012 compaction_job_stats, job_context->job_id);
4013 }
4014
4015 if (status.ok() || status.IsCompactionTooLarge() ||
4016 status.IsManualCompactionPaused()) {
4017 // Done
4018 } else if (status.IsColumnFamilyDropped() || status.IsShutdownInProgress()) {
4019 // Ignore compaction errors found during shutting down
4020 } else {
4021 ROCKS_LOG_WARN(immutable_db_options_.info_log, "Compaction error: %s",
4022 status.ToString().c_str());
4023 if (!io_s.ok()) {
4024 // Error while writing to MANIFEST.
4025 // In fact, versions_->io_status() can also be the result of renaming
4026 // CURRENT file. With current code, it's just difficult to tell. So just
4027 // be pessimistic and try write to a new MANIFEST.
4028 // TODO: distinguish between MANIFEST write and CURRENT renaming
4029 auto err_reason = versions_->io_status().ok()
4030 ? BackgroundErrorReason::kCompaction
4031 : BackgroundErrorReason::kManifestWrite;
4032 error_handler_.SetBGError(io_s, err_reason);
4033 } else {
4034 error_handler_.SetBGError(status, BackgroundErrorReason::kCompaction);
4035 }
4036 if (c != nullptr && !is_manual && !error_handler_.IsBGWorkStopped()) {
4037 // Put this cfd back in the compaction queue so we can retry after some
4038 // time
4039 auto cfd = c->column_family_data();
4040 assert(cfd != nullptr);
4041 // Since this compaction failed, we need to recompute the score so it
4042 // takes the original input files into account
4043 c->column_family_data()
4044 ->current()
4045 ->storage_info()
4046 ->ComputeCompactionScore(*(c->immutable_options()),
4047 *(c->mutable_cf_options()));
4048 if (!cfd->queued_for_compaction()) {
4050 }
4051 }
4052 }
4053 // this will unref its input_version and column_family_data
4054 c.reset();
4055
4056 if (is_manual) {
4057 ManualCompactionState* m = manual_compaction;
4058 if (!status.ok()) {
4059 m->status = status;
4060 m->done = true;
4061 }
4062 // For universal compaction:
4063 // Because universal compaction always happens at level 0, so one
4064 // compaction will pick up all overlapped files. No files will be
4065 // filtered out due to size limit and left for a successive compaction.
4066 // So we can safely conclude the current compaction.
4067 //
4068 // Also note that, if we don't stop here, then the current compaction
4069 // writes a new file back to level 0, which will be used in successive
4070 // compaction. Hence the manual compaction will never finish.
4071 //
4072 // Stop the compaction if manual_end points to nullptr -- this means
4073 // that we compacted the whole range. manual_end should always point
4074 // to nullptr in case of universal compaction
4075 if (m->manual_end == nullptr) {
4076 m->done = true;
4077 }
4078 if (!m->done) {
4079 // We only compacted part of the requested range. Update *m
4080 // to the range that is left to be compacted.
4081 // Universal and FIFO compactions should always compact the whole range
4082 assert(m->cfd->ioptions()->compaction_style !=
4083 kCompactionStyleUniversal ||
4084 m->cfd->ioptions()->num_levels > 1);
4085 assert(m->cfd->ioptions()->compaction_style != kCompactionStyleFIFO);
4086 m->tmp_storage = *m->manual_end;
4087 m->begin = &m->tmp_storage;
4088 m->incomplete = true;
4089 }
4090 m->in_progress = false; // not being processed anymore
4091 }
4092 TEST_SYNC_POINT("DBImpl::BackgroundCompaction:Finish");
4093 return status;
4094}
SnapshotList snapshots_
Definition db_impl.h:2800
void AddToCompactionQueue(ColumnFamilyData *cfd)
void UpdateDeletionCompactionStats(const std::unique_ptr< Compaction > &c)
ColumnFamilyData * PickCompactionFromQueue(std::unique_ptr< TaskLimiterToken > *token, LogBuffer *log_buffer)
void NotifyOnCompactionBegin(ColumnFamilyData *cfd, Compaction *c, const Status &st, const CompactionJobStats &job_stats, int job_id)
std::list< uint64_t >::iterator CaptureOptionsFileNumber()
Definition db_impl.cc:4848
void NotifyOnCompactionCompleted(ColumnFamilyData *cfd, Compaction *c, const Status &st, const CompactionJobStats &job_stats, int job_id)
void ReleaseOptionsFileNumber(std::unique_ptr< std::list< uint64_t >::iterator > &v)
Definition db_impl.cc:4858
bool EnoughRoomForCompaction(ColumnFamilyData *cfd, const std::vector< CompactionInputFiles > &inputs, bool *sfm_bookkeeping, LogBuffer *log_buffer)
const ImmutableDBOptions & immutable_db_options() const
Definition db_impl.h:892
virtual int GetBackgroundThreads(Priority pri=LOW)=0
virtual void Schedule(void(*function)(void *arg), void *arg, Priority pri=LOW, void *tag=nullptr, void(*unschedFunction)(void *arg)=nullptr)=0
EventLoggerStream LogToBuffer(LogBuffer *log_buffer)
#define ROCKS_LOG_WARN(LGR, FMT,...)
Definition logging.h:41
void RecordInHistogram(Statistics *statistics, uint32_t histogram_type, uint64_t value)
std::shared_ptr< CompactionService > compaction_service
Definition db_options.h:103
__attribute__((const, always_inline)) static inline intptr_t which_cache_line(intptr_t addr)
Definition toku_atomic.h:63
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BackgroundFlush()

Status ROCKSDB_NAMESPACE::DBImpl::BackgroundFlush ( bool * madeProgress,
JobContext * job_context,
LogBuffer * log_buffer,
FlushReason * reason,
bool * flush_rescheduled_to_retain_udt,
Env::Priority thread_pri )
private

db_impl_compaction_flush.cc 파일의 3165 번째 라인에서 정의되었습니다.

3168 {
3169 mutex_.AssertHeld();
3170
3171 Status status;
3172 *reason = FlushReason::kOthers;
3173 // If BG work is stopped due to an error, but a recovery is in progress,
3174 // that means this flush is part of the recovery. So allow it to go through
3176 if (shutting_down_.load(std::memory_order_acquire)) {
3177 status = Status::ShutdownInProgress();
3178 }
3179 } else if (!error_handler_.IsRecoveryInProgress()) {
3180 status = error_handler_.GetBGError();
3181 }
3182
3183 if (!status.ok()) {
3184 return status;
3185 }
3186
3187 autovector<BGFlushArg> bg_flush_args;
3188 std::vector<SuperVersionContext>& superversion_contexts =
3189 job_context->superversion_contexts;
3190 autovector<ColumnFamilyData*> column_families_not_to_flush;
3191 while (!flush_queue_.empty()) {
3192 // This cfd is already referenced
3193 FlushRequest flush_req = PopFirstFromFlushQueue();
3194 FlushReason flush_reason = flush_req.flush_reason;
3196 flush_reason != FlushReason::kErrorRecovery &&
3197 flush_reason != FlushReason::kErrorRecoveryRetryFlush) {
3198 // Stop non-recovery flush when bg work is stopped
3199 // Note that we drop the flush request here.
3200 // Recovery thread should schedule further flushes after bg error
3201 // is cleared.
3202 status = error_handler_.GetBGError();
3203 assert(!status.ok());
3204 ROCKS_LOG_BUFFER(log_buffer,
3205 "[JOB %d] Abort flush due to background error %s",
3206 job_context->job_id, status.ToString().c_str());
3207 *reason = flush_reason;
3208 for (auto item : flush_req.cfd_to_max_mem_id_to_persist) {
3209 item.first->UnrefAndTryDelete();
3210 }
3211 return status;
3212 }
3215 assert(flush_req.cfd_to_max_mem_id_to_persist.size() == 1);
3216 ColumnFamilyData* cfd =
3217 flush_req.cfd_to_max_mem_id_to_persist.begin()->first;
3218 if (cfd->UnrefAndTryDelete()) {
3219 return Status::OK();
3220 }
3221 ROCKS_LOG_BUFFER(log_buffer,
3222 "FlushRequest for column family %s is re-scheduled to "
3223 "retain user-defined timestamps.",
3224 cfd->GetName().c_str());
3225 // Reschedule the `FlushRequest` as is without checking dropped column
3226 // family etc. The follow-up job will do the check anyways, so save the
3227 // duplication. Column family is deduplicated by `SchdulePendingFlush` and
3228 // `PopFirstFromFlushQueue` contains at flush request enqueueing and
3229 // dequeueing time.
3230 // This flush request is rescheduled right after it's popped from the
3231 // queue while the db mutex is held, so there should be no other
3232 // FlushRequest for the same column family with higher `max_memtable_id`
3233 // in the queue to block the reschedule from succeeding.
3234#ifndef NDEBUG
3235 flush_req.reschedule_count += 1;
3236#endif /* !NDEBUG */
3237 EnqueuePendingFlush(flush_req);
3238 *reason = flush_reason;
3239 *flush_rescheduled_to_retain_udt = true;
3240 return Status::TryAgain();
3241 }
3242 superversion_contexts.clear();
3243 superversion_contexts.reserve(
3244 flush_req.cfd_to_max_mem_id_to_persist.size());
3245
3246 for (const auto& [cfd, max_memtable_id] :
3247 flush_req.cfd_to_max_mem_id_to_persist) {
3248 if (cfd->GetMempurgeUsed()) {
3249 // If imm() contains silent memtables (e.g.: because
3250 // MemPurge was activated), requesting a flush will
3251 // mark the imm_needed as true.
3252 cfd->imm()->FlushRequested();
3253 }
3254
3255 if (cfd->IsDropped() || !cfd->imm()->IsFlushPending()) {
3256 // can't flush this CF, try next one
3257 column_families_not_to_flush.push_back(cfd);
3258 continue;
3259 }
3260 superversion_contexts.emplace_back(true);
3261 bg_flush_args.emplace_back(cfd, max_memtable_id,
3262 &(superversion_contexts.back()), flush_reason);
3263 }
3264 // `MaybeScheduleFlushOrCompaction` schedules as many `BackgroundCallFlush`
3265 // jobs as the number of `FlushRequest` in the `flush_queue_`, a.k.a
3266 // `unscheduled_flushes_`. So it's sufficient to make each `BackgroundFlush`
3267 // handle one `FlushRequest` and each have a Status returned.
3268 if (!bg_flush_args.empty() || !column_families_not_to_flush.empty()) {
3269 TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundFlush:CheckFlushRequest:cb",
3270 const_cast<int*>(&flush_req.reschedule_count));
3271 break;
3272 }
3273 }
3274
3275 if (!bg_flush_args.empty()) {
3276 auto bg_job_limits = GetBGJobLimits();
3277 for (const auto& arg : bg_flush_args) {
3278 ColumnFamilyData* cfd = arg.cfd_;
3280 log_buffer,
3281 "Calling FlushMemTableToOutputFile with column "
3282 "family [%s], flush slots available %d, compaction slots available "
3283 "%d, "
3284 "flush slots scheduled %d, compaction slots scheduled %d",
3285 cfd->GetName().c_str(), bg_job_limits.max_flushes,
3286 bg_job_limits.max_compactions, bg_flush_scheduled_,
3287 bg_compaction_scheduled_);
3288 }
3289 status = FlushMemTablesToOutputFiles(bg_flush_args, made_progress,
3290 job_context, log_buffer, thread_pri);
3291 TEST_SYNC_POINT("DBImpl::BackgroundFlush:BeforeFlush");
3292// All the CFD/bg_flush_arg in the FlushReq must have the same flush reason, so
3293// just grab the first one
3294#ifndef NDEBUG
3295 for (const auto& bg_flush_arg : bg_flush_args) {
3296 assert(bg_flush_arg.flush_reason_ == bg_flush_args[0].flush_reason_);
3297 }
3298#endif /* !NDEBUG */
3299 *reason = bg_flush_args[0].flush_reason_;
3300 for (auto& arg : bg_flush_args) {
3301 ColumnFamilyData* cfd = arg.cfd_;
3302 if (cfd->UnrefAndTryDelete()) {
3303 arg.cfd_ = nullptr;
3304 }
3305 }
3306 }
3307 for (auto cfd : column_families_not_to_flush) {
3308 cfd->UnrefAndTryDelete();
3309 }
3310 return status;
3311}
bool ShouldRescheduleFlushRequestToRetainUDT(const FlushRequest &flush_req)
std::deque< FlushRequest > flush_queue_
Definition db_impl.h:2840
Status FlushMemTablesToOutputFiles(const autovector< BGFlushArg > &bg_flush_args, bool *made_progress, JobContext *job_context, LogBuffer *log_buffer, Env::Priority thread_pri)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BGWorkBottomCompaction()

void ROCKSDB_NAMESPACE::DBImpl::BGWorkBottomCompaction ( void * arg)
staticprivate

db_impl_compaction_flush.cc 파일의 3105 번째 라인에서 정의되었습니다.

3105 {
3106 CompactionArg ca = *(static_cast<CompactionArg*>(arg));
3107 delete static_cast<CompactionArg*>(arg);
3108 IOSTATS_SET_THREAD_POOL_ID(Env::Priority::BOTTOM);
3109 TEST_SYNC_POINT("DBImpl::BGWorkBottomCompaction");
3110 auto* prepicked_compaction = ca.prepicked_compaction;
3111 assert(prepicked_compaction && prepicked_compaction->compaction);
3112 ca.db->BackgroundCallCompaction(prepicked_compaction, Env::Priority::BOTTOM);
3113 delete prepicked_compaction;
3114}
#define IOSTATS_SET_THREAD_POOL_ID(value)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BGWorkCompaction()

void ROCKSDB_NAMESPACE::DBImpl::BGWorkCompaction ( void * arg)
staticprivate

db_impl_compaction_flush.cc 파일의 3093 번째 라인에서 정의되었습니다.

3093 {
3094 CompactionArg ca = *(static_cast<CompactionArg*>(arg));
3095 delete static_cast<CompactionArg*>(arg);
3096 IOSTATS_SET_THREAD_POOL_ID(Env::Priority::LOW);
3097 TEST_SYNC_POINT("DBImpl::BGWorkCompaction");
3098 auto prepicked_compaction =
3099 static_cast<PrepickedCompaction*>(ca.prepicked_compaction);
3100 static_cast_with_check<DBImpl>(ca.db)->BackgroundCallCompaction(
3101 prepicked_compaction, Env::Priority::LOW);
3102 delete prepicked_compaction;
3103}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BGWorkFlush()

void ROCKSDB_NAMESPACE::DBImpl::BGWorkFlush ( void * arg)
staticprivate

db_impl_compaction_flush.cc 파일의 3083 번째 라인에서 정의되었습니다.

3083 {
3084 FlushThreadArg fta = *(static_cast<FlushThreadArg*>(arg));
3085 delete static_cast<FlushThreadArg*>(arg);
3086
3087 IOSTATS_SET_THREAD_POOL_ID(fta.thread_pri_);
3088 TEST_SYNC_POINT("DBImpl::BGWorkFlush");
3089 static_cast_with_check<DBImpl>(fta.db_)->BackgroundCallFlush(fta.thread_pri_);
3090 TEST_SYNC_POINT("DBImpl::BGWorkFlush:done");
3091}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BGWorkPurge()

void ROCKSDB_NAMESPACE::DBImpl::BGWorkPurge ( void * arg)
staticprivate

db_impl_compaction_flush.cc 파일의 3116 번째 라인에서 정의되었습니다.

3116 {
3117 IOSTATS_SET_THREAD_POOL_ID(Env::Priority::HIGH);
3118 TEST_SYNC_POINT("DBImpl::BGWorkPurge:start");
3119 static_cast<DBImpl*>(db)->BackgroundCallPurge();
3120 TEST_SYNC_POINT("DBImpl::BGWorkPurge:end");
3121}
DBImpl(const DBOptions &options, const std::string &dbname, const bool seq_per_batch=false, const bool batch_per_txn=true, bool read_only=false)
Definition db_impl.cc:166
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ BuildCompactionJobInfo()

void ROCKSDB_NAMESPACE::DBImpl::BuildCompactionJobInfo ( const ColumnFamilyData * cfd,
Compaction * c,
const Status & st,
const CompactionJobStats & compaction_job_stats,
const int job_id,
CompactionJobInfo * compaction_job_info ) const
private

db_impl_compaction_flush.cc 파일의 4205 번째 라인에서 정의되었습니다.

4208 {
4209 assert(compaction_job_info != nullptr);
4210 compaction_job_info->cf_id = cfd->GetID();
4211 compaction_job_info->cf_name = cfd->GetName();
4212 compaction_job_info->status = st;
4213 compaction_job_info->thread_id = env_->GetThreadID();
4214 compaction_job_info->job_id = job_id;
4215 compaction_job_info->base_input_level = c->start_level();
4216 compaction_job_info->output_level = c->output_level();
4217 compaction_job_info->stats = compaction_job_stats;
4218 const auto& input_table_properties = c->GetOrInitInputTableProperties();
4219 const auto& output_table_properties = c->GetOutputTableProperties();
4220 compaction_job_info->table_properties.insert(input_table_properties.begin(),
4221 input_table_properties.end());
4222 compaction_job_info->table_properties.insert(output_table_properties.begin(),
4223 output_table_properties.end());
4224 compaction_job_info->compaction_reason = c->compaction_reason();
4225 compaction_job_info->compression = c->output_compression();
4226
4227 const ReadOptions read_options(Env::IOActivity::kCompaction);
4228 for (size_t i = 0; i < c->num_input_levels(); ++i) {
4229 for (const auto fmd : *c->inputs(i)) {
4230 const FileDescriptor& desc = fmd->fd;
4231 const uint64_t file_number = desc.GetNumber();
4232 auto fn = TableFileName(c->immutable_options()->cf_paths, file_number,
4233 desc.GetPathId());
4234 compaction_job_info->input_files.push_back(fn);
4235 compaction_job_info->input_file_infos.push_back(CompactionFileInfo{
4236 static_cast<int>(i), file_number, fmd->oldest_blob_file_number});
4237 }
4238 }
4239
4240 for (const auto& newf : c->edit()->GetNewFiles()) {
4241 const FileMetaData& meta = newf.second;
4242 const FileDescriptor& desc = meta.fd;
4243 const uint64_t file_number = desc.GetNumber();
4244 compaction_job_info->output_files.push_back(TableFileName(
4245 c->immutable_options()->cf_paths, file_number, desc.GetPathId()));
4246 compaction_job_info->output_file_infos.push_back(CompactionFileInfo{
4247 newf.first, file_number, meta.oldest_blob_file_number});
4248 }
4249 compaction_job_info->blob_compression_type =
4250 c->mutable_cf_options()->blob_compression_type;
4251
4252 // Update BlobFilesInfo.
4253 for (const auto& blob_file : c->edit()->GetBlobFileAdditions()) {
4254 BlobFileAdditionInfo blob_file_addition_info(
4255 BlobFileName(c->immutable_options()->cf_paths.front().path,
4256 blob_file.GetBlobFileNumber()) /*blob_file_path*/,
4257 blob_file.GetBlobFileNumber(), blob_file.GetTotalBlobCount(),
4258 blob_file.GetTotalBlobBytes());
4259 compaction_job_info->blob_file_addition_infos.emplace_back(
4260 std::move(blob_file_addition_info));
4261 }
4262
4263 // Update BlobFilesGarbageInfo.
4264 for (const auto& blob_file : c->edit()->GetBlobFileGarbages()) {
4265 BlobFileGarbageInfo blob_file_garbage_info(
4266 BlobFileName(c->immutable_options()->cf_paths.front().path,
4267 blob_file.GetBlobFileNumber()) /*blob_file_path*/,
4268 blob_file.GetBlobFileNumber(), blob_file.GetGarbageBlobCount(),
4269 blob_file.GetGarbageBlobBytes());
4270 compaction_job_info->blob_file_garbage_infos.emplace_back(
4271 std::move(blob_file_garbage_info));
4272 }
4273}
virtual uint64_t GetThreadID() const
Definition env.cc:734
std::string TableFileName(const std::vector< DbPath > &db_paths, uint64_t number, uint32_t path_id)
Definition filename.cc:140
std::string BlobFileName(uint64_t number)
Definition filename.cc:87
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CalculateWALWriteHint()

Env::WriteLifeTimeHint ROCKSDB_NAMESPACE::DBImpl::CalculateWALWriteHint ( )
inlineprivate

db_impl.h 파일의 2466 번째 라인에서 정의되었습니다.

2466{ return Env::WLTH_SHORT; }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CancelAllBackgroundWork()

void ROCKSDB_NAMESPACE::DBImpl::CancelAllBackgroundWork ( bool wait)

db_impl.cc 파일의 498 번째 라인에서 정의되었습니다.

498 {
500 "Shutdown: canceling all background work");
501 Status s = CancelPeriodicTaskScheduler();
502 s.PermitUncheckedError();
503
504 InstrumentedMutexLock l(&mutex_);
505 if (!shutting_down_.load(std::memory_order_acquire) &&
506 has_unpersisted_data_.load(std::memory_order_relaxed) &&
508 s = DBImpl::FlushAllColumnFamilies(FlushOptions(), FlushReason::kShutDown);
509 s.PermitUncheckedError(); //**TODO: What to do on error?
510 }
511
512 shutting_down_.store(true, std::memory_order_release);
514 if (!wait) {
515 return;
516 }
518}
Status CancelPeriodicTaskScheduler()
Definition db_impl.cc:970
#define ROCKS_LOG_INFO(LGR, FMT,...)
Definition logging.h:38
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CancelPeriodicTaskScheduler()

Status ROCKSDB_NAMESPACE::DBImpl::CancelPeriodicTaskScheduler ( )
private

db_impl.cc 파일의 970 번째 라인에서 정의되었습니다.

970 {
971 Status s = Status::OK();
972 for (uint8_t task_type = 0;
973 task_type < static_cast<uint8_t>(PeriodicTaskType::kMax); task_type++) {
975 static_cast<PeriodicTaskType>(task_type));
976 if (!s.ok()) {
978 "Failed to unregister periodic task %d, status: %s",
979 task_type, s.ToString().c_str());
980 }
981 }
982 return s;
983}
Status Unregister(PeriodicTaskType task_type)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CaptureCurrentFileNumberInPendingOutputs()

std::list< uint64_t >::iterator ROCKSDB_NAMESPACE::DBImpl::CaptureCurrentFileNumberInPendingOutputs ( )
private

db_impl.cc 파일의 4830 번째 라인에서 정의되었습니다.

4830 {
4831 // We need to remember the iterator of our insert, because after the
4832 // background job is done, we need to remove that element from
4833 // pending_outputs_.
4834 pending_outputs_.push_back(versions_->current_next_file_number());
4835 auto pending_outputs_inserted_elem = pending_outputs_.end();
4836 --pending_outputs_inserted_elem;
4837 return pending_outputs_inserted_elem;
4838}
std::list< uint64_t > pending_outputs_
Definition db_impl.h:2813
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CaptureOptionsFileNumber()

std::list< uint64_t >::iterator ROCKSDB_NAMESPACE::DBImpl::CaptureOptionsFileNumber ( )
private

db_impl.cc 파일의 4848 번째 라인에서 정의되었습니다.

4848 {
4849 // We need to remember the iterator of our insert, because after the
4850 // compaction is done, we need to remove that element from
4851 // min_options_file_numbers_.
4852 min_options_file_numbers_.push_back(versions_->options_file_number());
4853 auto min_options_file_numbers_inserted_elem = min_options_file_numbers_.end();
4854 --min_options_file_numbers_inserted_elem;
4855 return min_options_file_numbers_inserted_elem;
4856}
std::list< uint64_t > min_options_file_numbers_
Definition db_impl.h:2818
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CheckConsistency()

Status ROCKSDB_NAMESPACE::DBImpl::CheckConsistency ( )
virtual

ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 5145 번째 라인에서 정의되었습니다.

5145 {
5146 mutex_.AssertHeld();
5147 std::vector<LiveFileMetaData> metadata;
5148 versions_->GetLiveFilesMetaData(&metadata);
5149 TEST_SYNC_POINT("DBImpl::CheckConsistency:AfterGetLiveFilesMetaData");
5150
5151 std::string corruption_messages;
5152
5154 // Instead of calling GetFileSize() for each expected file, call
5155 // GetChildren() for the DB directory and check that all expected files
5156 // are listed, without checking their sizes.
5157 // Since sst files might be in different directories, do it for each
5158 // directory separately.
5159 std::map<std::string, std::vector<std::string>> files_by_directory;
5160 for (const auto& md : metadata) {
5161 // md.name has a leading "/". Remove it.
5162 std::string fname = md.name;
5163 if (!fname.empty() && fname[0] == '/') {
5164 fname = fname.substr(1);
5165 }
5166 files_by_directory[md.db_path].push_back(fname);
5167 }
5168
5169 IOOptions io_opts;
5170 io_opts.do_not_recurse = true;
5171 for (const auto& dir_files : files_by_directory) {
5172 std::string directory = dir_files.first;
5173 std::vector<std::string> existing_files;
5174 Status s = fs_->GetChildren(directory, io_opts, &existing_files,
5175 /*IODebugContext*=*/nullptr);
5176 if (!s.ok()) {
5177 corruption_messages +=
5178 "Can't list files in " + directory + ": " + s.ToString() + "\n";
5179 continue;
5180 }
5181 std::sort(existing_files.begin(), existing_files.end());
5182
5183 for (const std::string& fname : dir_files.second) {
5184 if (!std::binary_search(existing_files.begin(), existing_files.end(),
5185 fname) &&
5186 !std::binary_search(existing_files.begin(), existing_files.end(),
5187 Rocks2LevelTableFileName(fname))) {
5188 corruption_messages +=
5189 "Missing sst file " + fname + " in " + directory + "\n";
5190 }
5191 }
5192 }
5193 } else {
5194 for (const auto& md : metadata) {
5195 // md.name has a leading "/".
5196 std::string file_path = md.db_path + md.name;
5197
5198 uint64_t fsize = 0;
5199 TEST_SYNC_POINT("DBImpl::CheckConsistency:BeforeGetFileSize");
5200 Status s = env_->GetFileSize(file_path, &fsize);
5201 if (!s.ok() &&
5202 env_->GetFileSize(Rocks2LevelTableFileName(file_path), &fsize).ok()) {
5203 s = Status::OK();
5204 }
5205 if (!s.ok()) {
5206 corruption_messages +=
5207 "Can't access " + md.name + ": " + s.ToString() + "\n";
5208 } else if (fsize != md.size) {
5209 corruption_messages += "Sst file size mismatch: " + file_path +
5210 ". Size recorded in manifest " +
5211 std::to_string(md.size) + ", actual size " +
5212 std::to_string(fsize) + "\n";
5213 }
5214 }
5215 }
5216
5217 if (corruption_messages.size() == 0) {
5218 return Status::OK();
5219 } else {
5220 return Status::Corruption(corruption_messages);
5221 }
5222}
virtual Status GetFileSize(const std::string &fname, uint64_t *file_size)=0
std::string Rocks2LevelTableFileName(const std::string &fullname)
Definition filename.cc:120
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CleanupSuperVersion()

void ROCKSDB_NAMESPACE::DBImpl::CleanupSuperVersion ( SuperVersion * sv)

db_impl.cc 파일의 4684 번째 라인에서 정의되었습니다.

4684 {
4685 // Release SuperVersion
4686 if (sv->Unref()) {
4688 {
4689 InstrumentedMutexLock l(&mutex_);
4690 sv->Cleanup();
4691 if (defer_purge) {
4693 SchedulePurge();
4694 }
4695 }
4696 if (!defer_purge) {
4697 delete sv;
4698 }
4699 RecordTick(stats_, NUMBER_SUPERVERSION_CLEANUPS);
4700 }
4701 RecordTick(stats_, NUMBER_SUPERVERSION_RELEASES);
4702}
void AddSuperVersionsToFreeQueue(SuperVersion *sv)
Definition db_impl.h:1060
void RecordTick(Statistics *statistics, uint32_t ticker_type, uint64_t count=1)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ClipColumnFamily()

Status ROCKSDB_NAMESPACE::DBImpl::ClipColumnFamily ( ColumnFamilyHandle * column_family,
const Slice & begin_key,
const Slice & end_key )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly에서 재구현되었습니다.

db_impl.cc 파일의 6384 번째 라인에서 정의되었습니다.

6385 {
6386 assert(column_family);
6387 Status status;
6388 // Flush memtable
6389 FlushOptions flush_opts;
6390 flush_opts.allow_write_stall = true;
6391 auto* cfd =
6392 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
6394 status = AtomicFlushMemTables(flush_opts, FlushReason::kDeleteFiles,
6395 {} /* provided_candidate_cfds */,
6396 false /* entered_write_thread */);
6397 } else {
6398 status = FlushMemTable(cfd, flush_opts, FlushReason::kDeleteFiles,
6399 false /* entered_write_thread */);
6400 }
6401
6402 if (status.ok()) {
6403 // DeleteFilesInRanges non-overlap files except L0
6404 std::vector<RangePtr> ranges;
6405 ranges.emplace_back(nullptr, &begin_key);
6406 ranges.emplace_back(&end_key, nullptr);
6407 status = DeleteFilesInRanges(column_family, ranges.data(), ranges.size());
6408 }
6409
6410 // DeleteRange the remaining overlapping keys
6411 bool empty_after_delete = false;
6412 if (status.ok()) {
6413 Slice smallest_user_key, largest_user_key;
6414 {
6415 // Lock db mutex
6416 InstrumentedMutexLock l(&mutex_);
6417 cfd->current()->GetSstFilesBoundaryKeys(&smallest_user_key,
6418 &largest_user_key);
6419 }
6420 // all the files has been deleted after DeleteFilesInRanges;
6421 if (smallest_user_key.empty() && largest_user_key.empty()) {
6422 empty_after_delete = true;
6423 } else {
6424 const Comparator* const ucmp = column_family->GetComparator();
6425 // TODO: plumb Env::IOActivity, Env::IOPriority
6426 WriteOptions wo;
6427 // Delete [smallest_user_key, clip_begin_key)
6428 if (ucmp->Compare(smallest_user_key, begin_key) < 0) {
6429 status = DeleteRange(wo, column_family, smallest_user_key, begin_key);
6430 }
6431
6432 if (status.ok()) {
6433 // Delete [clip_end_key, largest_use_key]
6434 if (ucmp->Compare(end_key, largest_user_key) <= 0) {
6435 status = DeleteRange(wo, column_family, end_key, largest_user_key);
6436 if (status.ok()) {
6437 status = Delete(wo, column_family, largest_user_key);
6438 }
6439 }
6440 }
6441 }
6442 }
6443
6444 if (status.ok() && !empty_after_delete) {
6445 // CompactRange delete all the tombstones
6446 CompactRangeOptions compact_options;
6447 compact_options.exclusive_manual_compaction = true;
6448 compact_options.bottommost_level_compaction =
6449 BottommostLevelCompaction::kForceOptimized;
6450 // We could just compact the ranges [null, clip_begin_key] and
6451 // [clip_end_key, null]. But due to how manual compaction calculates the
6452 // last level to compact to and that range tombstones are not dropped
6453 // during non-bottommost compactions, calling CompactRange() on these two
6454 // ranges may not clear all range tombstones.
6455 status = CompactRange(compact_options, column_family, nullptr, nullptr);
6456 }
6457 return status;
6458}
Status FlushMemTable(ColumnFamilyData *cfd, const FlushOptions &options, FlushReason flush_reason, bool entered_write_thread=false)
Status DeleteRange(const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &begin_key, const Slice &end_key) override
Status DeleteFilesInRanges(ColumnFamilyHandle *column_family, const RangePtr *ranges, size_t n, bool include_end=true)
Definition db_impl.cc:4985
Status CompactRange(const CompactRangeOptions &options, ColumnFamilyHandle *column_family, const Slice *begin, const Slice *end) override
Status AtomicFlushMemTables(const FlushOptions &options, FlushReason flush_reason, const autovector< ColumnFamilyData * > &provided_candidate_cfds={}, bool entered_write_thread=false)
Status Delete(const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key) override
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Close()

Status ROCKSDB_NAMESPACE::DBImpl::Close ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplFollower에서 재구현되었습니다.

db_impl.cc 파일의 5321 번째 라인에서 정의되었습니다.

5321 {
5322 InstrumentedMutexLock closing_lock_guard(&closing_mutex_);
5323 if (closed_) {
5324 return closing_status_;
5325 }
5326
5327 {
5329 if (!s.ok()) {
5330 return s;
5331 }
5332 }
5333
5335 closed_ = true;
5336 return closing_status_;
5337}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CloseHelper()

Status ROCKSDB_NAMESPACE::DBImpl::CloseHelper ( )
private

db_impl.cc 파일의 538 번째 라인에서 정의되었습니다.

538 {
539 // Guarantee that there is no background error recovery in progress before
540 // continuing with the shutdown
541 mutex_.Lock();
542 shutdown_initiated_ = true;
545 bg_cv_.Wait();
546 }
547 mutex_.Unlock();
548
549 // Below check is added as recovery_error_ is not checked and it causes crash
550 // in DBSSTTest.DBWithMaxSpaceAllowedWithBlobFiles when space limit is
551 // reached.
553
554 // CancelAllBackgroundWork called with false means we just set the shutdown
555 // marker. After this we do a variant of the waiting and unschedule work
556 // (to consider: moving all the waiting into CancelAllBackgroundWork(true))
558
559 // Cancel manual compaction if there's any
562 }
563 mutex_.Lock();
564 // Unschedule all tasks for this DB
565 for (uint8_t i = 0; i < static_cast<uint8_t>(TaskType::kCount); i++) {
566 env_->UnSchedule(GetTaskTag(i), Env::Priority::BOTTOM);
567 env_->UnSchedule(GetTaskTag(i), Env::Priority::LOW);
568 env_->UnSchedule(GetTaskTag(i), Env::Priority::HIGH);
569 }
570
571 Status ret = Status::OK();
572
573 // Wait for background work to finish
574 while (bg_bottom_compaction_scheduled_ || bg_compaction_scheduled_ ||
575 bg_flush_scheduled_ || bg_purge_scheduled_ ||
576 pending_purge_obsolete_files_ ||
578 TEST_SYNC_POINT("DBImpl::~DBImpl:WaitJob");
579 bg_cv_.Wait();
580 }
581 TEST_SYNC_POINT_CALLBACK("DBImpl::CloseHelper:PendingPurgeFinished",
582 &files_grabbed_for_purge_);
586
587 while (!flush_queue_.empty()) {
588 const FlushRequest& flush_req = PopFirstFromFlushQueue();
589 for (const auto& iter : flush_req.cfd_to_max_mem_id_to_persist) {
590 iter.first->UnrefAndTryDelete();
591 }
592 }
593
594 while (!compaction_queue_.empty()) {
595 auto cfd = PopFirstFromCompactionQueue();
596 cfd->UnrefAndTryDelete();
597 }
598
599 if (default_cf_handle_ != nullptr || persist_stats_cf_handle_ != nullptr) {
600 // we need to delete handle outside of lock because it does its own locking
601 mutex_.Unlock();
602 if (default_cf_handle_) {
603 delete default_cf_handle_;
604 default_cf_handle_ = nullptr;
605 }
606 if (persist_stats_cf_handle_) {
608 persist_stats_cf_handle_ = nullptr;
609 }
610 mutex_.Lock();
611 }
612
613 // Clean up obsolete files due to SuperVersion release.
614 // (1) Need to delete to obsolete files before closing because RepairDB()
615 // scans all existing files in the file system and builds manifest file.
616 // Keeping obsolete files confuses the repair process.
617 // (2) Need to check if we Open()/Recover() the DB successfully before
618 // deleting because if VersionSet recover fails (may be due to corrupted
619 // manifest file), it is not able to identify live files correctly. As a
620 // result, all "live" files can get deleted by accident. However, corrupted
621 // manifest is recoverable by RepairDB().
622 if (opened_successfully_) {
623 JobContext job_context(next_job_id_.fetch_add(1));
624 FindObsoleteFiles(&job_context, true);
625
626 mutex_.Unlock();
627 // manifest number starting from 2
628 job_context.manifest_file_number = 1;
629 if (job_context.HaveSomethingToDelete()) {
630 PurgeObsoleteFiles(job_context);
631 }
632 job_context.Clean();
633 mutex_.Lock();
634 }
635 {
636 InstrumentedMutexLock lock(&log_write_mutex_);
637 for (auto l : logs_to_free_) {
638 delete l;
639 }
640 for (auto& log : logs_) {
641 uint64_t log_number = log.writer->get_log_number();
642 Status s = log.ClearWriter();
643 if (!s.ok()) {
646 "Unable to clear writer for WAL %s with error -- %s",
647 LogFileName(immutable_db_options_.GetWalDir(), log_number).c_str(),
648 s.ToString().c_str());
649 // Retain the first error
650 if (ret.ok()) {
651 ret = s;
652 }
653 }
654 }
655 logs_.clear();
656 }
657
658 // Table cache may have table handles holding blocks from the block cache.
659 // We need to release them before the block cache is destroyed. The block
660 // cache may be destroyed inside versions_.reset(), when column family data
661 // list is destroyed, so leaving handles in table cache after
662 // versions_.reset() may cause issues. Here we clean all unreferenced handles
663 // in table cache, and (for certain builds/conditions) assert that no obsolete
664 // files are hanging around unreferenced (leak) in the table/blob file cache.
665 // Now we assume all user queries have finished, so only version set itself
666 // can possibly hold the blocks from block cache. After releasing unreferenced
667 // handles here, only handles held by version set left and inside
668 // versions_.reset(), we will release them. There, we need to make sure every
669 // time a handle is released, we erase it from the cache too. By doing that,
670 // we can guarantee that after versions_.reset(), table cache is empty
671 // so the cache can be safely destroyed.
672#ifndef NDEBUG
673 TEST_VerifyNoObsoleteFilesCached(/*db_mutex_already_held=*/true);
674#endif // !NDEBUG
675 table_cache_->EraseUnRefEntries();
676
677 for (auto& txn_entry : recovered_transactions_) {
678 delete txn_entry.second;
679 }
680
681 // Return an unowned SstFileManager to a consistent state
682 if (immutable_db_options_.sst_file_manager && !own_sfm_) {
683 mutex_.Unlock();
685 mutex_.Lock();
686 }
687
688 // versions need to be destroyed before table_cache since it can hold
689 // references to table_cache.
690 {
691 Status s = versions_->Close(directories_.GetDbDir(), &mutex_);
692 if (!s.ok()) {
694 "Unable to close MANIFEST with error -- %s",
695 s.ToString().c_str());
696 if (ret.ok()) {
697 ret = s;
698 }
699 }
700 }
701
702 versions_.reset();
703 mutex_.Unlock();
704 if (db_lock_ != nullptr) {
705 // TODO: Check for unlock error
707 }
708
709 ROCKS_LOG_INFO(immutable_db_options_.info_log, "Shutdown complete");
711
712 // If the sst_file_manager was allocated by us during DB::Open(), ccall
713 // Close() on it before closing the info_log. Otherwise, background thread
714 // in SstFileManagerImpl might try to log something
715 if (immutable_db_options_.sst_file_manager && own_sfm_) {
716 auto sfm = static_cast<SstFileManagerImpl*>(
718 sfm->Close();
719 }
720
721 if (immutable_db_options_.info_log && own_info_log_) {
722 Status s = immutable_db_options_.info_log->Close();
723 if (!s.ok() && !s.IsNotSupported() && ret.ok()) {
724 ret = s;
725 }
726 }
727
728 if (write_buffer_manager_ && wbm_stall_) {
730 }
731
732 IOStatus io_s = directories_.Close(IOOptions(), nullptr /* dbg */);
733 if (!io_s.ok()) {
734 ret = io_s;
735 }
736 if (ret.IsAborted()) {
737 // Reserve IsAborted() error for those where users didn't release
738 // certain resource and they can release them and come back and
739 // retry. In this case, we wrap this exception to something else.
740 return Status::Incomplete(ret.ToString());
741 }
742
743 return ret;
744}
ColumnFamilyData * PopFirstFromCompactionQueue()
void CancelAllBackgroundWork(bool wait)
Definition db_impl.cc:498
void EraseThreadStatusDbInfo() const
Definition db_impl.cc:5703
FlushScheduler flush_scheduler_
Definition db_impl.h:2796
TrimHistoryScheduler trim_history_scheduler_
Definition db_impl.h:2798
void TEST_VerifyNoObsoleteFilesCached(bool db_mutex_already_held) const
void * GetTaskTag(TaskType type)
Definition db_impl.h:2193
IOStatus Close(const IOOptions &options, IODebugContext *dbg)
Definition db_impl.h:116
virtual Status UnlockFile(FileLock *lock)=0
virtual int UnSchedule(void *, Priority)
Definition env.h:481
void RemoveDBFromQueue(StallInterface *wbm_stall)
std::string LogFileName(const std::string &name, uint64_t number)
Definition filename.cc:77
const std::string & GetWalDir() const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CloseImpl()

Status ROCKSDB_NAMESPACE::DBImpl::CloseImpl ( )
protectedvirtual

db_impl.cc 파일의 746 번째 라인에서 정의되었습니다.

746{ return CloseHelper(); }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CollectAllDBPaths()

std::set< std::string > ROCKSDB_NAMESPACE::DBImpl::CollectAllDBPaths ( )
protected

db_impl_files.cc 파일의 1035 번째 라인에서 정의되었습니다.

1035 {
1036 std::set<std::string> all_db_paths;
1037 all_db_paths.insert(NormalizePath(dbname_));
1038 for (const auto& db_path : immutable_db_options_.db_paths) {
1039 all_db_paths.insert(NormalizePath(db_path.path));
1040 }
1041 for (const auto* cfd : *versions_->GetColumnFamilySet()) {
1042 for (const auto& cf_path : cfd->ioptions()->cf_paths) {
1043 all_db_paths.insert(NormalizePath(cf_path.path));
1044 }
1045 }
1046 return all_db_paths;
1047}
constexpr char db_path[]
Definition db_fuzzer.cc:25
std::string NormalizePath(const std::string &path)
Definition filename.cc:528
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CompactFiles() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::CompactFiles ( const CompactionOptions & compact_options,
ColumnFamilyHandle * column_family,
const std::vector< std::string > & input_file_names,
const int output_level,
const int output_path_id = -1,
std::vector< std::string > *const output_file_names = nullptr,
CompactionJobInfo * compaction_job_info = nullptr )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_compaction_flush.cc 파일의 1367 번째 라인에서 정의되었습니다.

1372 {
1373 if (column_family == nullptr) {
1374 return Status::InvalidArgument("ColumnFamilyHandle must be non-null.");
1375 }
1376
1377 auto cfd =
1378 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
1379 assert(cfd);
1380
1381 Status s;
1382 JobContext job_context(next_job_id_.fetch_add(1), true);
1383 LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL,
1385
1386 if (compact_options.compression !=
1387 CompressionType::kDisableCompressionOption) {
1389 "[%s] [JOB %d] Found use of deprecated option "
1390 "`CompactionOptions::compression`",
1391 cfd->GetName().c_str(), job_context.job_id);
1392 }
1393
1394 // Perform CompactFiles
1395 TEST_SYNC_POINT("TestCompactFiles::IngestExternalFile2");
1396 TEST_SYNC_POINT_CALLBACK("TestCompactFiles:PausingManualCompaction:3",
1397 static_cast<void*>(const_cast<std::atomic<int>*>(
1398 &manual_compaction_paused_)));
1399 {
1400 InstrumentedMutexLock l(&mutex_);
1401 auto* current = cfd->current();
1402 current->Ref();
1403
1404 s = CompactFilesImpl(compact_options, cfd, current, input_file_names,
1405 output_file_names, output_level, output_path_id,
1406 &job_context, &log_buffer, compaction_job_info);
1407
1408 current->Unref();
1409 }
1410
1411 // Find and delete obsolete files
1412 {
1413 InstrumentedMutexLock l(&mutex_);
1414 // If !s.ok(), this means that Compaction failed. In that case, we want
1415 // to delete all obsolete files we might have created and we force
1416 // FindObsoleteFiles(). This is because job_context does not
1417 // catch all created files if compaction failed.
1418 FindObsoleteFiles(&job_context, !s.ok());
1419 } // release the mutex
1420
1421 // delete unnecessary files if any, this is done outside the mutex
1422 if (job_context.HaveSomethingToClean() ||
1423 job_context.HaveSomethingToDelete() || !log_buffer.IsEmpty()) {
1424 // Have to flush the info logs before bg_compaction_scheduled_--
1425 // because if bg_flush_scheduled_ becomes 0 and the lock is
1426 // released, the deconstructor of DB can kick in and destroy all the
1427 // states of DB so info_log might not be available after that point.
1428 // It also applies to access other states that DB owns.
1429 log_buffer.FlushBufferToLog();
1430 if (job_context.HaveSomethingToDelete()) {
1431 // no mutex is locked here. No need to Unlock() and Lock() here.
1432 PurgeObsoleteFiles(job_context);
1433 }
1434 job_context.Clean();
1435 }
1436
1437 return s;
1438}
Status CompactFilesImpl(const CompactionOptions &compact_options, ColumnFamilyData *cfd, Version *version, const std::vector< std::string > &input_file_names, std::vector< std::string > *const output_file_names, const int output_level, int output_path_id, JobContext *job_context, LogBuffer *log_buffer, CompactionJobInfo *compaction_job_info)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CompactFiles() [2/2]

virtual Status ROCKSDB_NAMESPACE::DB::CompactFiles ( const CompactionOptions & compact_options,
const std::vector< std::string > & input_file_names,
const int output_level,
const int output_path_id = -1,
std::vector< std::string > *const output_file_names = nullptr,
CompactionJobInfo * compaction_job_info = nullptr )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 1557 번째 라인에서 정의되었습니다.

1562 {
1563 return CompactFiles(compact_options, DefaultColumnFamily(),
1564 input_file_names, output_level, output_path_id,
1565 output_file_names, compaction_job_info);
1566 }
Status CompactFiles(const CompactionOptions &compact_options, ColumnFamilyHandle *column_family, const std::vector< std::string > &input_file_names, const int output_level, const int output_path_id=-1, std::vector< std::string > *const output_file_names=nullptr, CompactionJobInfo *compaction_job_info=nullptr) override
ColumnFamilyHandle * DefaultColumnFamily() const override
Definition db_impl.cc:2152

◆ CompactFilesImpl()

Status ROCKSDB_NAMESPACE::DBImpl::CompactFilesImpl ( const CompactionOptions & compact_options,
ColumnFamilyData * cfd,
Version * version,
const std::vector< std::string > & input_file_names,
std::vector< std::string > *const output_file_names,
const int output_level,
int output_path_id,
JobContext * job_context,
LogBuffer * log_buffer,
CompactionJobInfo * compaction_job_info )
private

db_impl_compaction_flush.cc 파일의 1440 번째 라인에서 정의되었습니다.

1445 {
1446 mutex_.AssertHeld();
1447
1448 if (shutting_down_.load(std::memory_order_acquire)) {
1449 return Status::ShutdownInProgress();
1450 }
1451 if (manual_compaction_paused_.load(std::memory_order_acquire) > 0) {
1452 return Status::Incomplete(Status::SubCode::kManualCompactionPaused);
1453 }
1454
1455 std::unordered_set<uint64_t> input_set;
1456 for (const auto& file_name : input_file_names) {
1457 input_set.insert(TableFileNameToNumber(file_name));
1458 }
1459
1460 if (output_path_id < 0) {
1461 if (cfd->ioptions()->cf_paths.size() == 1U) {
1462 output_path_id = 0;
1463 } else {
1464 return Status::NotSupported(
1465 "Automatic output path selection is not "
1466 "yet supported in CompactFiles()");
1467 }
1468 }
1469
1470 if (cfd->ioptions()->allow_ingest_behind &&
1471 output_level >= cfd->ioptions()->num_levels - 1) {
1472 return Status::InvalidArgument(
1473 "Exceed the maximum output level defined by "
1474 "the current compaction algorithm with ingest_behind --- " +
1475 std::to_string(cfd->ioptions()->num_levels - 1));
1476 }
1477
1478 std::vector<CompactionInputFiles> input_files;
1479 Status s = cfd->compaction_picker()->SanitizeAndConvertCompactionInputFiles(
1480 &input_set, output_level, version, &input_files);
1482 "DBImpl::CompactFilesImpl::PostSanitizeAndConvertCompactionInputFiles");
1483 if (!s.ok()) {
1484 return s;
1485 }
1486
1487 for (const auto& inputs : input_files) {
1488 if (cfd->compaction_picker()->AreFilesInCompaction(inputs.files)) {
1489 return Status::Aborted(
1490 "Some of the necessary compaction input "
1491 "files are already being compacted");
1492 }
1493 }
1494 bool sfm_reserved_compact_space = false;
1495 // First check if we have enough room to do the compaction
1496 bool enough_room = EnoughRoomForCompaction(
1497 cfd, input_files, &sfm_reserved_compact_space, log_buffer);
1498
1499 if (!enough_room) {
1500 // m's vars will get set properly at the end of this function,
1501 // as long as status == CompactionTooLarge
1502 return Status::CompactionTooLarge();
1503 }
1504
1505 // At this point, CompactFiles will be run.
1507
1508 std::unique_ptr<Compaction> c;
1509 assert(cfd->compaction_picker());
1510 c.reset(cfd->compaction_picker()->CompactFiles(
1511 compact_options, input_files, output_level, version->storage_info(),
1512 *cfd->GetLatestMutableCFOptions(), mutable_db_options_, output_path_id));
1513 // we already sanitized the set of input files and checked for conflicts
1514 // without releasing the lock, so we're guaranteed a compaction can be formed.
1515 assert(c != nullptr);
1516
1517 c->FinalizeInputInfo(version);
1518
1519 // deletion compaction currently not allowed in CompactFiles.
1520 assert(!c->deletion_compaction());
1521
1522 std::vector<SequenceNumber> snapshot_seqs;
1523 SequenceNumber earliest_write_conflict_snapshot;
1524 SnapshotChecker* snapshot_checker;
1525 GetSnapshotContext(job_context, &snapshot_seqs,
1526 &earliest_write_conflict_snapshot, &snapshot_checker);
1527
1528 std::unique_ptr<std::list<uint64_t>::iterator> pending_outputs_inserted_elem(
1529 new std::list<uint64_t>::iterator(
1531
1532 assert(is_snapshot_supported_ || snapshots_.empty());
1533 CompactionJobStats compaction_job_stats;
1534 CompactionJob compaction_job(
1535 job_context->job_id, c.get(), immutable_db_options_, mutable_db_options_,
1536 file_options_for_compaction_, versions_.get(), &shutting_down_,
1537 log_buffer, directories_.GetDbDir(),
1538 GetDataDir(c->column_family_data(), c->output_path_id()),
1539 GetDataDir(c->column_family_data(), 0), stats_, &mutex_, &error_handler_,
1540 snapshot_seqs, earliest_write_conflict_snapshot, snapshot_checker,
1541 job_context, table_cache_, &event_logger_,
1542 c->mutable_cf_options()->paranoid_file_checks,
1543 c->mutable_cf_options()->report_bg_io_stats, dbname_,
1544 &compaction_job_stats, Env::Priority::USER, io_tracer_,
1545 kManualCompactionCanceledFalse_, db_id_, db_session_id_,
1546 c->column_family_data()->GetFullHistoryTsLow(), c->trim_ts(),
1547 &blob_callback_, &bg_compaction_scheduled_,
1548 &bg_bottom_compaction_scheduled_);
1549
1550 // Creating a compaction influences the compaction score because the score
1551 // takes running compactions into account (by skipping files that are already
1552 // being compacted). Since we just changed compaction score, we recalculate it
1553 // here.
1554 version->storage_info()->ComputeCompactionScore(*cfd->ioptions(),
1555 *c->mutable_cf_options());
1556
1557 compaction_job.Prepare();
1558
1559 std::unique_ptr<std::list<uint64_t>::iterator> min_options_file_number_elem;
1560 if (immutable_db_options().compaction_service != nullptr) {
1561 min_options_file_number_elem.reset(
1562 new std::list<uint64_t>::iterator(CaptureOptionsFileNumber()));
1563 }
1564
1565 mutex_.Unlock();
1566 TEST_SYNC_POINT("CompactFilesImpl:0");
1567 TEST_SYNC_POINT("CompactFilesImpl:1");
1568 // Ignore the status here, as it will be checked in the Install down below...
1569 compaction_job.Run().PermitUncheckedError();
1570 TEST_SYNC_POINT("CompactFilesImpl:2");
1571 TEST_SYNC_POINT("CompactFilesImpl:3");
1572 mutex_.Lock();
1573
1574 if (immutable_db_options().compaction_service != nullptr) {
1575 ReleaseOptionsFileNumber(min_options_file_number_elem);
1576 }
1577
1578 bool compaction_released = false;
1579 Status status =
1580 compaction_job.Install(*c->mutable_cf_options(), &compaction_released);
1581 if (!compaction_released) {
1582 c->ReleaseCompactionFiles(s);
1583 }
1584 if (status.ok()) {
1585 assert(compaction_job.io_status().ok());
1587 c->column_family_data(), job_context->superversion_contexts.data(),
1588 *c->mutable_cf_options());
1589 }
1590 // status above captures any error during compaction_job.Install, so its ok
1591 // not check compaction_job.io_status() explicitly if we're not calling
1592 // SetBGError
1593 compaction_job.io_status().PermitUncheckedError();
1594 // Need to make sure SstFileManager does its bookkeeping
1595 auto sfm = static_cast<SstFileManagerImpl*>(
1597 if (sfm && sfm_reserved_compact_space) {
1598 sfm->OnCompactionCompletion(c.get());
1599 }
1600
1601 ReleaseFileNumberFromPendingOutputs(pending_outputs_inserted_elem);
1602
1603 mutex_.Unlock();
1604 if (compaction_job_info != nullptr) {
1605 BuildCompactionJobInfo(cfd, c.get(), s, compaction_job_stats,
1606 job_context->job_id, compaction_job_info);
1607 }
1608 mutex_.Lock();
1609
1610 if (status.ok()) {
1611 // Done
1612 } else if (status.IsColumnFamilyDropped() || status.IsShutdownInProgress()) {
1613 // Ignore compaction errors found during shutting down
1614 } else if (status.IsManualCompactionPaused()) {
1615 // Don't report stopping manual compaction as error
1617 "[%s] [JOB %d] Stopping manual compaction",
1618 c->column_family_data()->GetName().c_str(),
1619 job_context->job_id);
1620 } else {
1622 "[%s] [JOB %d] Compaction error: %s",
1623 c->column_family_data()->GetName().c_str(),
1624 job_context->job_id, status.ToString().c_str());
1625 IOStatus io_s = compaction_job.io_status();
1626 if (!io_s.ok()) {
1627 error_handler_.SetBGError(io_s, BackgroundErrorReason::kCompaction);
1628 } else {
1629 error_handler_.SetBGError(status, BackgroundErrorReason::kCompaction);
1630 }
1631 }
1632
1633 if (output_file_names != nullptr) {
1634 for (const auto& newf : c->edit()->GetNewFiles()) {
1635 output_file_names->push_back(TableFileName(
1636 c->immutable_options()->cf_paths, newf.second.fd.GetNumber(),
1637 newf.second.fd.GetPathId()));
1638 }
1639
1640 for (const auto& blob_file : c->edit()->GetBlobFileAdditions()) {
1641 output_file_names->push_back(
1642 BlobFileName(c->immutable_options()->cf_paths.front().path,
1643 blob_file.GetBlobFileNumber()));
1644 }
1645 }
1646
1647 c.reset();
1648
1650 if (bg_compaction_scheduled_ == 0) {
1651 bg_cv_.SignalAll();
1652 }
1654 TEST_SYNC_POINT("CompactFilesImpl:End");
1655
1656 return status;
1657}
void BuildCompactionJobInfo(const ColumnFamilyData *cfd, Compaction *c, const Status &st, const CompactionJobStats &compaction_job_stats, const int job_id, CompactionJobInfo *compaction_job_info) const
uint64_t TableFileNameToNumber(const std::string &name)
Definition filename.cc:129
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CompactRange() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::CompactRange ( const CompactRangeOptions & options,
ColumnFamilyHandle * column_family,
const Slice * begin,
const Slice * end )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_compaction_flush.cc 파일의 965 번째 라인에서 정의되었습니다.

968 {
969 if (manual_compaction_paused_.load(std::memory_order_acquire) > 0) {
970 return Status::Incomplete(Status::SubCode::kManualCompactionPaused);
971 }
972
973 if (options.canceled && options.canceled->load(std::memory_order_acquire)) {
974 return Status::Incomplete(Status::SubCode::kManualCompactionPaused);
975 }
976
977 const Comparator* const ucmp = column_family->GetComparator();
978 assert(ucmp);
979 size_t ts_sz = ucmp->timestamp_size();
980 if (ts_sz == 0) {
981 return CompactRangeInternal(options, column_family, begin_without_ts,
982 end_without_ts, "" /*trim_ts*/);
983 }
984
985 std::string begin_str, end_str;
986 auto [begin, end] =
987 MaybeAddTimestampsToRange(begin_without_ts, end_without_ts, ts_sz,
988 &begin_str, &end_str, false /*exclusive_end*/);
989
991 options, column_family, begin.has_value() ? &begin.value() : nullptr,
992 end.has_value() ? &end.value() : nullptr, "" /*trim_ts*/);
993}
Status CompactRangeInternal(const CompactRangeOptions &options, ColumnFamilyHandle *column_family, const Slice *begin, const Slice *end, const std::string &trim_ts)
std::tuple< std::optional< Slice >, std::optional< Slice > > MaybeAddTimestampsToRange(const Slice *start, const Slice *end, size_t ts_sz, std::string *start_with_ts, std::string *end_with_ts, bool exclusive_end)
Definition udt_util.cc:433
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CompactRange() [2/2]

virtual Status ROCKSDB_NAMESPACE::DB::CompactRange ( const CompactRangeOptions & options,
const Slice * begin,
const Slice * end )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 1496 번째 라인에서 정의되었습니다.

1497 {
1498 return CompactRange(options, DefaultColumnFamily(), begin, end);
1499 }

◆ CompactRangeInternal()

Status ROCKSDB_NAMESPACE::DBImpl::CompactRangeInternal ( const CompactRangeOptions & options,
ColumnFamilyHandle * column_family,
const Slice * begin,
const Slice * end,
const std::string & trim_ts )
protected

db_impl_compaction_flush.cc 파일의 1062 번째 라인에서 정의되었습니다.

1065 {
1066 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1067 auto cfd = cfh->cfd();
1068
1069 if (options.target_path_id >= cfd->ioptions()->cf_paths.size()) {
1070 return Status::InvalidArgument("Invalid target path ID");
1071 }
1072 if (options.change_level &&
1073 cfd->ioptions()->compaction_style == kCompactionStyleFIFO) {
1074 return Status::NotSupported(
1075 "FIFO compaction does not support change_level.");
1076 }
1077
1078 bool flush_needed = true;
1079
1080 // Update full_history_ts_low if it's set
1081 if (options.full_history_ts_low != nullptr &&
1082 !options.full_history_ts_low->empty()) {
1083 std::string ts_low = options.full_history_ts_low->ToString();
1084 if (begin != nullptr || end != nullptr) {
1085 return Status::InvalidArgument(
1086 "Cannot specify compaction range with full_history_ts_low");
1087 }
1088 Status s = IncreaseFullHistoryTsLowImpl(cfd, ts_low);
1089 if (!s.ok()) {
1091 return s;
1092 }
1093 }
1094
1095 Status s;
1096 if (begin != nullptr && end != nullptr) {
1097 // TODO(ajkr): We could also optimize away the flush in certain cases where
1098 // one/both sides of the interval are unbounded. But it requires more
1099 // changes to RangesOverlapWithMemtables.
1100 UserKeyRange range(*begin, *end);
1101 SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
1102 s = cfd->RangesOverlapWithMemtables(
1103 {range}, super_version, immutable_db_options_.allow_data_in_errors,
1104 &flush_needed);
1105 CleanupSuperVersion(super_version);
1106 }
1107
1108 if (s.ok() && flush_needed) {
1109 FlushOptions fo;
1110 fo.allow_write_stall = options.allow_write_stall;
1112 s = AtomicFlushMemTables(fo, FlushReason::kManualCompaction);
1113 } else {
1114 s = FlushMemTable(cfd, fo, FlushReason::kManualCompaction);
1115 }
1116 if (!s.ok()) {
1118 return s;
1119 }
1120 }
1121
1122 constexpr int kInvalidLevel = -1;
1123 int final_output_level = kInvalidLevel;
1124 bool exclusive = options.exclusive_manual_compaction;
1125 if (cfd->ioptions()->compaction_style == kCompactionStyleUniversal &&
1126 cfd->NumberLevels() > 1) {
1127 // Always compact all files together.
1128 final_output_level = cfd->NumberLevels() - 1;
1129 // if bottom most level is reserved
1131 final_output_level--;
1132 }
1133 s = RunManualCompaction(cfd, ColumnFamilyData::kCompactAllLevels,
1134 final_output_level, options, begin, end, exclusive,
1135 false /* disable_trivial_move */,
1136 std::numeric_limits<uint64_t>::max(), trim_ts);
1137 } else if (cfd->ioptions()->compaction_style == kCompactionStyleFIFO) {
1138 // FIFOCompactionPicker::CompactRange() will ignore the input key range
1139 // [begin, end] and just try to pick compaction based on the configured
1140 // option `compaction_options_fifo`. So we skip checking if [begin, end]
1141 // overlaps with the DB here.
1142 final_output_level = 0;
1143 s = RunManualCompaction(cfd, /*input_level=*/0, final_output_level, options,
1144 begin, end, exclusive,
1145 false /* disable_trivial_move */,
1146 std::numeric_limits<uint64_t>::max(), trim_ts);
1147 } else {
1148 int first_overlapped_level = kInvalidLevel;
1149 {
1150 SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
1151 Version* current_version = super_version->current;
1152
1153 // Might need to query the partitioner
1154 SstPartitionerFactory* partitioner_factory =
1155 current_version->cfd()->ioptions()->sst_partitioner_factory.get();
1156 std::unique_ptr<SstPartitioner> partitioner;
1157 if (partitioner_factory && begin != nullptr && end != nullptr) {
1158 SstPartitioner::Context context;
1159 context.is_full_compaction = false;
1160 context.is_manual_compaction = true;
1161 context.output_level = /*unknown*/ -1;
1162 // Small lies about compaction range
1163 context.smallest_user_key = *begin;
1164 context.largest_user_key = *end;
1165 partitioner = partitioner_factory->CreatePartitioner(context);
1166 }
1167
1168 ReadOptions ro;
1169 ro.total_order_seek = true;
1170 ro.io_activity = Env::IOActivity::kCompaction;
1171 bool overlap;
1172 for (int level = 0;
1173 level < current_version->storage_info()->num_non_empty_levels();
1174 level++) {
1175 overlap = true;
1176
1177 // Whether to look at specific keys within files for overlap with
1178 // compaction range, other than largest and smallest keys of the file
1179 // known in Version metadata.
1180 bool check_overlap_within_file = false;
1181 if (begin != nullptr && end != nullptr) {
1182 // Typically checking overlap within files in this case
1183 check_overlap_within_file = true;
1184 // WART: Not known why we don't check within file in one-sided bound
1185 // cases
1186 if (partitioner) {
1187 // Especially if the partitioner is new, the manual compaction
1188 // might be used to enforce the partitioning. Checking overlap
1189 // within files might miss cases where compaction is needed to
1190 // partition the files, as in this example:
1191 // * File has two keys "001" and "111"
1192 // * Compaction range is ["011", "101")
1193 // * Partition boundary at "100"
1194 // In cases like this, file-level overlap with the compaction
1195 // range is sufficient to force any partitioning that is needed
1196 // within the compaction range.
1197 //
1198 // But if there's no partitioning boundary within the compaction
1199 // range, we can be sure there's no need to fix partitioning
1200 // within that range, thus safe to check overlap within file.
1201 //
1202 // Use a hypothetical trivial move query to check for partition
1203 // boundary in range. (NOTE: in defiance of all conventions,
1204 // `begin` and `end` here are both INCLUSIVE bounds, which makes
1205 // this analogy to CanDoTrivialMove() accurate even when `end` is
1206 // the first key in a partition.)
1207 if (!partitioner->CanDoTrivialMove(*begin, *end)) {
1208 check_overlap_within_file = false;
1209 }
1210 }
1211 }
1212 if (check_overlap_within_file) {
1213 Status status = current_version->OverlapWithLevelIterator(
1214 ro, file_options_, *begin, *end, level, &overlap);
1215 if (!status.ok()) {
1216 check_overlap_within_file = false;
1217 }
1218 }
1219 if (!check_overlap_within_file) {
1220 overlap = current_version->storage_info()->OverlapInLevel(level,
1221 begin, end);
1222 }
1223 if (overlap) {
1224 first_overlapped_level = level;
1225 break;
1226 }
1227 }
1228 CleanupSuperVersion(super_version);
1229 }
1230 if (s.ok() && first_overlapped_level != kInvalidLevel) {
1231 if (cfd->ioptions()->compaction_style == kCompactionStyleUniversal) {
1232 assert(first_overlapped_level == 0);
1234 cfd, first_overlapped_level, first_overlapped_level, options, begin,
1235 end, exclusive, true /* disallow_trivial_move */,
1236 std::numeric_limits<uint64_t>::max() /* max_file_num_to_ignore */,
1237 trim_ts);
1238 final_output_level = first_overlapped_level;
1239 } else {
1240 assert(cfd->ioptions()->compaction_style == kCompactionStyleLevel);
1241 uint64_t next_file_number = versions_->current_next_file_number();
1242 // Start compaction from `first_overlapped_level`, one level down at a
1243 // time, until output level >= max_overlapped_level.
1244 // When max_overlapped_level == 0, we will still compact from L0 -> L1
1245 // (or LBase), and followed by a bottommost level intra-level compaction
1246 // at L1 (or LBase), if applicable.
1247 int level = first_overlapped_level;
1248 final_output_level = level;
1249 int output_level = 0, base_level = 0;
1250 for (;;) {
1251 // Always allow L0 -> L1 compaction
1252 if (level > 0) {
1253 if (cfd->ioptions()->level_compaction_dynamic_level_bytes) {
1254 assert(final_output_level < cfd->ioptions()->num_levels);
1255 if (final_output_level + 1 == cfd->ioptions()->num_levels) {
1256 break;
1257 }
1258 } else {
1259 // TODO(cbi): there is still a race condition here where
1260 // if a background compaction compacts some file beyond
1261 // current()->storage_info()->num_non_empty_levels() right after
1262 // the check here.This should happen very infrequently and should
1263 // not happen once a user populates the last level of the LSM.
1264 InstrumentedMutexLock l(&mutex_);
1265 // num_non_empty_levels may be lower after a compaction, so
1266 // we check for >= here.
1267 if (final_output_level + 1 >=
1268 cfd->current()->storage_info()->num_non_empty_levels()) {
1269 break;
1270 }
1271 }
1272 }
1273 output_level = level + 1;
1274 if (cfd->ioptions()->level_compaction_dynamic_level_bytes &&
1275 level == 0) {
1276 output_level = ColumnFamilyData::kCompactToBaseLevel;
1277 }
1278 // Use max value for `max_file_num_to_ignore` to always compact
1279 // files down.
1281 cfd, level, output_level, options, begin, end, exclusive,
1282 !trim_ts.empty() /* disallow_trivial_move */,
1283 std::numeric_limits<uint64_t>::max() /* max_file_num_to_ignore */,
1284 trim_ts,
1285 output_level == ColumnFamilyData::kCompactToBaseLevel
1286 ? &base_level
1287 : nullptr);
1288 if (!s.ok()) {
1289 break;
1290 }
1291 if (output_level == ColumnFamilyData::kCompactToBaseLevel) {
1292 assert(base_level > 0);
1293 level = base_level;
1294 } else {
1295 ++level;
1296 }
1297 final_output_level = level;
1298 TEST_SYNC_POINT("DBImpl::RunManualCompaction()::1");
1299 TEST_SYNC_POINT("DBImpl::RunManualCompaction()::2");
1300 }
1301 if (s.ok()) {
1302 assert(final_output_level > 0);
1303 // bottommost level intra-level compaction
1304 if ((options.bottommost_level_compaction ==
1305 BottommostLevelCompaction::kIfHaveCompactionFilter &&
1306 (cfd->ioptions()->compaction_filter != nullptr ||
1307 cfd->ioptions()->compaction_filter_factory != nullptr)) ||
1308 options.bottommost_level_compaction ==
1309 BottommostLevelCompaction::kForceOptimized ||
1310 options.bottommost_level_compaction ==
1311 BottommostLevelCompaction::kForce) {
1312 // Use `next_file_number` as `max_file_num_to_ignore` to avoid
1313 // rewriting newly compacted files when it is kForceOptimized
1314 // or kIfHaveCompactionFilter with compaction filter set.
1316 cfd, final_output_level, final_output_level, options, begin,
1317 end, exclusive, true /* disallow_trivial_move */,
1318 next_file_number /* max_file_num_to_ignore */, trim_ts);
1319 }
1320 }
1321 }
1322 }
1323 }
1324 if (!s.ok() || final_output_level == kInvalidLevel) {
1326 return s;
1327 }
1328
1329 if (options.change_level) {
1330 TEST_SYNC_POINT("DBImpl::CompactRange:BeforeRefit:1");
1331 TEST_SYNC_POINT("DBImpl::CompactRange:BeforeRefit:2");
1332
1334 "[RefitLevel] waiting for background threads to stop");
1335 // TODO(hx235): remove `Enable/DisableManualCompaction` and
1336 // `Continue/PauseBackgroundWork` once we ensure registering RefitLevel()'s
1337 // range is sufficient (if not, what else is needed) for avoiding range
1338 // conflicts with other activities (e.g, compaction, flush) that are
1339 // currently avoided by `Enable/DisableManualCompaction` and
1340 // `Continue/PauseBackgroundWork`.
1342 s = PauseBackgroundWork();
1343 if (s.ok()) {
1344 TEST_SYNC_POINT("DBImpl::CompactRange:PreRefitLevel");
1345 s = ReFitLevel(cfd, final_output_level, options.target_level);
1346 TEST_SYNC_POINT("DBImpl::CompactRange:PostRefitLevel");
1347 // ContinueBackgroundWork always return Status::OK().
1348 Status temp_s = ContinueBackgroundWork();
1349 assert(temp_s.ok());
1350 }
1353 "DBImpl::CompactRange:PostRefitLevel:ManualCompactionEnabled");
1354 }
1356
1357 {
1358 InstrumentedMutexLock l(&mutex_);
1359 // an automatic compaction that has been scheduled might have been
1360 // preempted by the manual compactions. Need to schedule it back.
1362 }
1363
1364 return s;
1365}
Status IncreaseFullHistoryTsLowImpl(ColumnFamilyData *cfd, std::string ts_low)
Status RunManualCompaction(ColumnFamilyData *cfd, int input_level, int output_level, const CompactRangeOptions &compact_range_options, const Slice *begin, const Slice *end, bool exclusive, bool disallow_trivial_move, uint64_t max_file_num_to_ignore, const std::string &trim_ts, int *final_output_level=nullptr)
void CleanupSuperVersion(SuperVersion *sv)
Definition db_impl.cc:4684
Status ReFitLevel(ColumnFamilyData *cfd, int level, int target_level=-1)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ConcurrentWriteToWAL()

IOStatus ROCKSDB_NAMESPACE::DBImpl::ConcurrentWriteToWAL ( const WriteThread::WriteGroup & write_group,
uint64_t * log_used,
SequenceNumber * last_sequence,
size_t seq_inc )
private

db_impl_write.cc 파일의 1719 번째 라인에서 정의되었습니다.

1721 {
1722 IOStatus io_s;
1723
1724 assert(two_write_queues_ || immutable_db_options_.unordered_write);
1725 assert(!write_group.leader->disable_wal);
1726 // Same holds for all in the batch group
1727 WriteBatch tmp_batch;
1728 size_t write_with_wal = 0;
1729 WriteBatch* to_be_cached_state = nullptr;
1730 WriteBatch* merged_batch;
1731 io_s = status_to_io_status(MergeBatch(write_group, &tmp_batch, &merged_batch,
1732 &write_with_wal, &to_be_cached_state));
1733 if (UNLIKELY(!io_s.ok())) {
1734 return io_s;
1735 }
1736
1737 // We need to lock log_write_mutex_ since logs_ and alive_log_files might be
1738 // pushed back concurrently
1740 if (merged_batch == write_group.leader->batch) {
1741 write_group.leader->log_used = logfile_number_;
1742 } else if (write_with_wal > 1) {
1743 for (auto writer : write_group) {
1744 writer->log_used = logfile_number_;
1745 }
1746 }
1747 *last_sequence = versions_->FetchAddLastAllocatedSequence(seq_inc);
1748 auto sequence = *last_sequence + 1;
1749 WriteBatchInternal::SetSequence(merged_batch, sequence);
1750
1751 log::Writer* log_writer = logs_.back().writer;
1752 LogFileNumberSize& log_file_number_size = alive_log_files_.back();
1753
1754 assert(log_writer->get_log_number() == log_file_number_size.number);
1755
1756 uint64_t log_size;
1757
1758 // TODO: plumb Env::IOActivity, Env::IOPriority
1759 WriteOptions write_options;
1760 write_options.rate_limiter_priority =
1761 write_group.leader->rate_limiter_priority;
1762 io_s = WriteToWAL(*merged_batch, write_options, log_writer, log_used,
1763 &log_size, log_file_number_size);
1764 if (to_be_cached_state) {
1765 cached_recoverable_state_ = *to_be_cached_state;
1767 }
1769
1770 if (io_s.ok()) {
1771 const bool concurrent = true;
1772 auto stats = default_cf_internal_stats_;
1773 stats->AddDBStats(InternalStats::kIntStatsWalFileBytes, log_size,
1774 concurrent);
1775 RecordTick(stats_, WAL_FILE_BYTES, log_size);
1776 stats->AddDBStats(InternalStats::kIntStatsWriteWithWal, write_with_wal,
1777 concurrent);
1778 RecordTick(stats_, WRITE_WITH_WAL, write_with_wal);
1779 for (auto* writer : write_group) {
1780 if (!writer->CallbackFailed()) {
1781 writer->CheckPostWalWriteCallback();
1782 }
1783 }
1784 }
1785 return io_s;
1786}
Status MergeBatch(const WriteThread::WriteGroup &write_group, WriteBatch *tmp_batch, WriteBatch **merged_batch, size_t *write_with_wal, WriteBatch **to_be_cached_state)
std::deque< LogWriterNumber > logs_
Definition db_impl.h:2751
std::deque< LogFileNumberSize > alive_log_files_
Definition db_impl.h:2696
WriteBatch cached_recoverable_state_
Definition db_impl.h:2762
IOStatus WriteToWAL(const WriteBatch &merged_batch, const WriteOptions &write_options, log::Writer *log_writer, uint64_t *log_used, uint64_t *log_size, LogFileNumberSize &log_file_number_size)
InstrumentedMutex log_write_mutex_
Definition db_impl.h:2615
void AddDBStats(InternalDBStatsType type, uint64_t value, bool concurrent=false)
#define UNLIKELY(x)
Definition likely.h:17
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ContinueBackgroundWork()

Status ROCKSDB_NAMESPACE::DBImpl::ContinueBackgroundWork ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 1670 번째 라인에서 정의되었습니다.

1670 {
1671 InstrumentedMutexLock guard_lock(&mutex_);
1672 if (bg_work_paused_ == 0) {
1673 return Status::InvalidArgument("Background work already unpaused");
1674 }
1675 assert(bg_work_paused_ > 0);
1676 assert(bg_compaction_paused_ > 0);
1679 // It's sufficient to check just bg_work_paused_ here since
1680 // bg_work_paused_ is always no greater than bg_compaction_paused_
1681 if (bg_work_paused_ == 0) {
1683 }
1684 return Status::OK();
1685}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateAndNewDirectory()

IOStatus ROCKSDB_NAMESPACE::DBImpl::CreateAndNewDirectory ( FileSystem * fs,
const std::string & dirname,
std::unique_ptr< FSDirectory > * directory )
static

db_impl_open.cc 파일의 363 번째 라인에서 정의되었습니다.

365 {
366 // We call CreateDirIfMissing() as the directory may already exist (if we
367 // are reopening a DB), when this happens we don't want creating the
368 // directory to cause an error. However, we need to check if creating the
369 // directory fails or else we may get an obscure message about the lock
370 // file not existing. One real-world example of this occurring is if
371 // env->CreateDirIfMissing() doesn't create intermediate directories, e.g.
372 // when dbname_ is "dir/db" but when "dir" doesn't exist.
373 IOStatus io_s = fs->CreateDirIfMissing(dirname, IOOptions(), nullptr);
374 if (!io_s.ok()) {
375 return io_s;
376 }
377 return fs->NewDirectory(dirname, IOOptions(), directory, nullptr);
378}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateArchivalDirectory()

const Status ROCKSDB_NAMESPACE::DBImpl::CreateArchivalDirectory ( )
private

db_impl.cc 파일의 781 번째 라인에서 정의되었습니다.

781 {
784 std::string archivalPath =
786 return env_->CreateDirIfMissing(archivalPath);
787 }
788 return Status::OK();
789}
virtual Status CreateDirIfMissing(const std::string &dirname)=0
std::string ArchivalDirectory(const std::string &dir)
Definition filename.cc:104
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamilies() [1/4]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamilies ( const ColumnFamilyOptions & cf_options,
const std::vector< std::string > & column_family_names,
std::vector< ColumnFamilyHandle * > * handles )
inlineoverridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.h 파일의 319 번째 라인에서 정의되었습니다.

322 {
323 // TODO: plumb Env::IOActivity, Env::IOPriority
324 return CreateColumnFamilies(ReadOptions(), WriteOptions(), cf_options,
325 column_family_names, handles);
326 }
Status CreateColumnFamilies(const ColumnFamilyOptions &cf_options, const std::vector< std::string > &column_family_names, std::vector< ColumnFamilyHandle * > *handles) override
Definition db_impl.h:319
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamilies() [2/4]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamilies ( const ReadOptions & read_options,
const WriteOptions & write_options,
const ColumnFamilyOptions & cf_options,
const std::vector< std::string > & column_family_names,
std::vector< ColumnFamilyHandle * > * handles )
virtual

db_impl.cc 파일의 3539 번째 라인에서 정의되었습니다.

3543 {
3544 assert(handles != nullptr);
3545 InstrumentedMutexLock ol(&options_mutex_);
3546 handles->clear();
3547 size_t num_cf = column_family_names.size();
3548 Status s;
3549 bool success_once = false;
3550 for (size_t i = 0; i < num_cf; i++) {
3551 ColumnFamilyHandle* handle;
3552 s = CreateColumnFamilyImpl(read_options, write_options, cf_options,
3553 column_family_names[i], &handle);
3554 if (!s.ok()) {
3555 break;
3556 }
3557 handles->push_back(handle);
3558 success_once = true;
3559 }
3560 if (success_once) {
3561 s.UpdateIfOk(
3562 WrapUpCreateColumnFamilies(read_options, write_options, {&cf_options}));
3563 }
3564 return s;
3565}
Status WrapUpCreateColumnFamilies(const ReadOptions &read_options, const WriteOptions &write_options, const std::vector< const ColumnFamilyOptions * > &cf_options)
Definition db_impl.cc:3499
Status CreateColumnFamilyImpl(const ReadOptions &read_options, const WriteOptions &write_options, const ColumnFamilyOptions &cf_options, const std::string &cf_name, ColumnFamilyHandle **handle)
Definition db_impl.cc:3598
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamilies() [3/4]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamilies ( const ReadOptions & read_options,
const WriteOptions & write_options,
const std::vector< ColumnFamilyDescriptor > & column_families,
std::vector< ColumnFamilyHandle * > * handles )
virtual

db_impl.cc 파일의 3567 번째 라인에서 정의되었습니다.

3570 {
3571 assert(handles != nullptr);
3572 InstrumentedMutexLock ol(&options_mutex_);
3573 handles->clear();
3574 size_t num_cf = column_families.size();
3575 Status s;
3576 bool success_once = false;
3577 std::vector<const ColumnFamilyOptions*> cf_opts;
3578 cf_opts.reserve(num_cf);
3579 for (size_t i = 0; i < num_cf; i++) {
3580 ColumnFamilyHandle* handle;
3581 s = CreateColumnFamilyImpl(read_options, write_options,
3582 column_families[i].options,
3583 column_families[i].name, &handle);
3584 if (!s.ok()) {
3585 break;
3586 }
3587 handles->push_back(handle);
3588 success_once = true;
3589 cf_opts.push_back(&column_families[i].options);
3590 }
3591 if (success_once) {
3592 s.UpdateIfOk(
3593 WrapUpCreateColumnFamilies(read_options, write_options, cf_opts));
3594 }
3595 return s;
3596}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamilies() [4/4]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamilies ( const std::vector< ColumnFamilyDescriptor > & column_families,
std::vector< ColumnFamilyHandle * > * handles )
inlineoverridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.h 파일의 333 번째 라인에서 정의되었습니다.

335 {
336 // TODO: plumb Env::IOActivity, Env::IOPriority
337 return CreateColumnFamilies(ReadOptions(), WriteOptions(), column_families,
338 handles);
339 }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamily() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamily ( const ColumnFamilyOptions & cf_options,
const std::string & column_family,
ColumnFamilyHandle ** handle )
inlineoverridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.h 파일의 307 번째 라인에서 정의되었습니다.

309 {
310 // TODO: plumb Env::IOActivity, Env::IOPriority
311 return CreateColumnFamily(ReadOptions(), WriteOptions(), cf_options,
312 column_family, handle);
313 }
Status CreateColumnFamily(const ColumnFamilyOptions &cf_options, const std::string &column_family, ColumnFamilyHandle **handle) override
Definition db_impl.h:307
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamily() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamily ( const ReadOptions & read_options,
const WriteOptions & write_options,
const ColumnFamilyOptions & cf_options,
const std::string & column_family,
ColumnFamilyHandle ** handle )
virtual

db_impl.cc 파일의 3523 번째 라인에서 정의되었습니다.

3527 {
3528 assert(handle != nullptr);
3529 InstrumentedMutexLock ol(&options_mutex_);
3530 Status s = CreateColumnFamilyImpl(read_options, write_options, cf_options,
3531 column_family, handle);
3532 if (s.ok()) {
3533 s.UpdateIfOk(
3534 WrapUpCreateColumnFamilies(read_options, write_options, {&cf_options}));
3535 }
3536 return s;
3537}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamilyImpl()

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamilyImpl ( const ReadOptions & read_options,
const WriteOptions & write_options,
const ColumnFamilyOptions & cf_options,
const std::string & cf_name,
ColumnFamilyHandle ** handle )
private

db_impl.cc 파일의 3598 번째 라인에서 정의되었습니다.

3602 {
3604 Status s;
3605 *handle = nullptr;
3606
3607 DBOptions db_options =
3608 BuildDBOptions(immutable_db_options_, mutable_db_options_);
3609 s = ColumnFamilyData::ValidateOptions(db_options, cf_options);
3610 if (s.ok()) {
3611 for (auto& cf_path : cf_options.cf_paths) {
3612 s = env_->CreateDirIfMissing(cf_path.path);
3613 if (!s.ok()) {
3614 break;
3615 }
3616 }
3617 }
3618 if (!s.ok()) {
3619 return s;
3620 }
3621
3622 SuperVersionContext sv_context(/* create_superversion */ true);
3623 {
3624 InstrumentedMutexLock l(&mutex_);
3625
3626 if (versions_->GetColumnFamilySet()->GetColumnFamily(column_family_name) !=
3627 nullptr) {
3628 return Status::InvalidArgument("Column family already exists");
3629 }
3630 VersionEdit edit;
3631 edit.AddColumnFamily(column_family_name);
3632 uint32_t new_id = versions_->GetColumnFamilySet()->GetNextColumnFamilyID();
3633 edit.SetColumnFamily(new_id);
3634 edit.SetLogNumber(logfile_number_);
3635 edit.SetComparatorName(cf_options.comparator->Name());
3636 edit.SetPersistUserDefinedTimestamps(
3637 cf_options.persist_user_defined_timestamps);
3638
3639 // LogAndApply will both write the creation in MANIFEST and create
3640 // ColumnFamilyData object
3641 { // write thread
3642 WriteThread::Writer w;
3643 write_thread_.EnterUnbatched(&w, &mutex_);
3644 // LogAndApply will both write the creation in MANIFEST and create
3645 // ColumnFamilyData object
3646 s = versions_->LogAndApply(nullptr, MutableCFOptions(cf_options),
3647 read_options, write_options, &edit, &mutex_,
3648 directories_.GetDbDir(), false, &cf_options);
3650 }
3651 if (s.ok()) {
3652 auto* cfd =
3653 versions_->GetColumnFamilySet()->GetColumnFamily(column_family_name);
3654 assert(cfd != nullptr);
3655 std::map<std::string, std::shared_ptr<FSDirectory>> dummy_created_dirs;
3656 s = cfd->AddDirectories(&dummy_created_dirs);
3657 }
3658 if (s.ok()) {
3659 auto* cfd =
3660 versions_->GetColumnFamilySet()->GetColumnFamily(column_family_name);
3661 assert(cfd != nullptr);
3662 InstallSuperVersionAndScheduleWork(cfd, &sv_context,
3663 *cfd->GetLatestMutableCFOptions());
3664
3665 if (!cfd->mem()->IsSnapshotSupported()) {
3666 is_snapshot_supported_ = false;
3667 }
3668
3669 cfd->set_initialized();
3670
3671 *handle = new ColumnFamilyHandleImpl(cfd, this, &mutex_);
3673 "Created column family [%s] (ID %u)",
3674 column_family_name.c_str(), (unsigned)cfd->GetID());
3675 } else {
3677 "Creating column family [%s] FAILED -- %s",
3678 column_family_name.c_str(), s.ToString().c_str());
3679 }
3680 } // InstrumentedMutexLock l(&mutex_)
3681
3682 sv_context.Clean();
3683 // this is outside the mutex
3684 if (s.ok()) {
3686 static_cast_with_check<ColumnFamilyHandleImpl>(*handle)->cfd());
3687 }
3688 return s;
3689}
void NewThreadStatusCfInfo(ColumnFamilyData *cfd) const
Definition db_impl.cc:5699
InstrumentedMutex options_mutex_
Definition db_impl.h:2604
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateColumnFamilyWithImport() [1/2]

virtual Status ROCKSDB_NAMESPACE::DB::CreateColumnFamilyWithImport ( const ColumnFamilyOptions & options,
const std::string & column_family_name,
const ImportColumnFamilyOptions & import_options,
const ExportImportFilesMetaData & metadata,
ColumnFamilyHandle ** handle )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly에서 재구현되었습니다.

db.h 파일의 1943 번째 라인에서 정의되었습니다.

1946 {
1947 const std::vector<const ExportImportFilesMetaData*>& metadatas{&metadata};
1948 return CreateColumnFamilyWithImport(options, column_family_name,
1949 import_options, metadatas, handle);
1950 }
Status CreateColumnFamilyWithImport(const ColumnFamilyOptions &options, const std::string &column_family_name, const ImportColumnFamilyOptions &import_options, const std::vector< const ExportImportFilesMetaData * > &metadatas, ColumnFamilyHandle **handle) override
Definition db_impl.cc:6239

◆ CreateColumnFamilyWithImport() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::CreateColumnFamilyWithImport ( const ColumnFamilyOptions & options,
const std::string & column_family_name,
const ImportColumnFamilyOptions & import_options,
const std::vector< const ExportImportFilesMetaData * > & metadatas,
ColumnFamilyHandle ** handle )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly에서 재구현되었습니다.

db_impl.cc 파일의 6239 번째 라인에서 정의되었습니다.

6243 {
6244 assert(handle != nullptr);
6245 assert(*handle == nullptr);
6246 // TODO: plumb Env::IOActivity, Env::IOPriority
6247 const ReadOptions read_options;
6248 const WriteOptions write_options;
6249
6250 std::string cf_comparator_name = options.comparator->Name();
6251
6252 size_t total_file_num = 0;
6253 std::vector<std::vector<LiveFileMetaData*>> metadata_files(metadatas.size());
6254 for (size_t i = 0; i < metadatas.size(); i++) {
6255 if (cf_comparator_name != metadatas[i]->db_comparator_name) {
6256 return Status::InvalidArgument("Comparator name mismatch");
6257 }
6258 for (auto& file : metadatas[i]->files) {
6259 metadata_files[i].push_back((LiveFileMetaData*)&file);
6260 }
6261 total_file_num += metadatas[i]->files.size();
6262 }
6263
6264 // Create column family.
6265 auto status = CreateColumnFamily(read_options, write_options, options,
6266 column_family_name, handle);
6267 if (!status.ok()) {
6268 return status;
6269 }
6270
6271 // Import sst files from metadata.
6272 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(*handle);
6273 auto cfd = cfh->cfd();
6274 ImportColumnFamilyJob import_job(versions_.get(), cfd, immutable_db_options_,
6275 file_options_, import_options,
6276 metadata_files, io_tracer_);
6277
6278 SuperVersionContext dummy_sv_ctx(/* create_superversion */ true);
6279 VersionEdit dummy_edit;
6280 uint64_t next_file_number = 0;
6281 std::unique_ptr<std::list<uint64_t>::iterator> pending_output_elem;
6282 {
6283 // Lock db mutex
6284 InstrumentedMutexLock l(&mutex_);
6286 // Don't import files when there is a bg_error
6287 status = error_handler_.GetBGError();
6288 }
6289
6290 // Make sure that bg cleanup wont delete the files that we are importing
6291 pending_output_elem.reset(new std::list<uint64_t>::iterator(
6293
6294 if (status.ok()) {
6295 // If crash happen after a hard link established, Recover function may
6296 // reuse the file number that has already assigned to the internal file,
6297 // and this will overwrite the external file. To protect the external
6298 // file, we have to make sure the file number will never being reused.
6299 next_file_number = versions_->FetchAddFileNumber(total_file_num);
6300 auto cf_options = cfd->GetLatestMutableCFOptions();
6301 status =
6302 versions_->LogAndApply(cfd, *cf_options, read_options, write_options,
6303 &dummy_edit, &mutex_, directories_.GetDbDir());
6304 if (status.ok()) {
6305 InstallSuperVersionAndScheduleWork(cfd, &dummy_sv_ctx, *cf_options);
6306 }
6307 }
6308 }
6309 dummy_sv_ctx.Clean();
6310
6311 if (status.ok()) {
6312 SuperVersion* sv = cfd->GetReferencedSuperVersion(this);
6313 status = import_job.Prepare(next_file_number, sv);
6315 }
6316
6317 if (status.ok()) {
6318 SuperVersionContext sv_context(true /*create_superversion*/);
6319 {
6320 // Lock db mutex
6321 InstrumentedMutexLock l(&mutex_);
6322
6323 // Stop writes to the DB by entering both write threads
6324 WriteThread::Writer w;
6325 write_thread_.EnterUnbatched(&w, &mutex_);
6326 WriteThread::Writer nonmem_w;
6327 if (two_write_queues_) {
6328 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
6329 }
6330
6332 assert(!cfd->IsDropped());
6333 mutex_.AssertHeld();
6334 status = import_job.Run();
6335
6336 // Install job edit [Mutex will be unlocked here]
6337 if (status.ok()) {
6338 auto cf_options = cfd->GetLatestMutableCFOptions();
6339 status = versions_->LogAndApply(cfd, *cf_options, read_options,
6340 write_options, import_job.edit(),
6341 &mutex_, directories_.GetDbDir());
6342 if (status.ok()) {
6343 InstallSuperVersionAndScheduleWork(cfd, &sv_context, *cf_options);
6344 }
6345 }
6346
6347 // Resume writes to the DB
6348 if (two_write_queues_) {
6350 }
6352
6354 if (num_running_ingest_file_ == 0) {
6355 bg_cv_.SignalAll();
6356 }
6357 }
6358 // mutex_ is unlocked here
6359
6360 sv_context.Clean();
6361 }
6362
6363 {
6364 InstrumentedMutexLock l(&mutex_);
6365 ReleaseFileNumberFromPendingOutputs(pending_output_elem);
6366 }
6367
6368 import_job.Cleanup(status);
6369 if (!status.ok()) {
6370 Status temp_s = DropColumnFamily(*handle);
6371 if (!temp_s.ok()) {
6373 "DropColumnFamily failed with error %s",
6374 temp_s.ToString().c_str());
6375 }
6376 // Always returns Status::OK()
6377 temp_s = DestroyColumnFamilyHandle(*handle);
6378 assert(temp_s.ok());
6379 *handle = nullptr;
6380 }
6381 return status;
6382}
Status DropColumnFamily(ColumnFamilyHandle *column_family) override
Definition db_impl.cc:3691
virtual Status DestroyColumnFamilyHandle(ColumnFamilyHandle *column_family)
Definition db_impl.cc:5310
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateTimestampedSnapshot()

std::pair< Status, std::shared_ptr< const Snapshot > > ROCKSDB_NAMESPACE::DBImpl::CreateTimestampedSnapshot ( SequenceNumber snapshot_seq,
uint64_t ts )

db_impl.cc 파일의 4136 번째 라인에서 정의되었습니다.

4136 {
4137 assert(ts != std::numeric_limits<uint64_t>::max());
4138
4139 auto ret = CreateTimestampedSnapshotImpl(snapshot_seq, ts, /*lock=*/true);
4140 return ret;
4141}
std::pair< Status, std::shared_ptr< const SnapshotImpl > > CreateTimestampedSnapshotImpl(SequenceNumber snapshot_seq, uint64_t ts, bool lock=true)
Definition db_impl.cc:4207
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateTimestampedSnapshotImpl()

std::pair< Status, std::shared_ptr< const SnapshotImpl > > ROCKSDB_NAMESPACE::DBImpl::CreateTimestampedSnapshotImpl ( SequenceNumber snapshot_seq,
uint64_t ts,
bool lock = true )
private

db_impl.cc 파일의 4207 번째 라인에서 정의되었습니다.

4208 {
4209 int64_t unix_time = 0;
4211 .PermitUncheckedError(); // Ignore error
4212 SnapshotImpl* s = new SnapshotImpl;
4213
4214 const bool need_update_seq = (snapshot_seq != kMaxSequenceNumber);
4215
4216 if (lock) {
4217 mutex_.Lock();
4218 } else {
4219 mutex_.AssertHeld();
4220 }
4221 // returns null if the underlying memtable does not support snapshot.
4222 if (!is_snapshot_supported_) {
4223 if (lock) {
4224 mutex_.Unlock();
4225 }
4226 delete s;
4227 return std::make_pair(
4228 Status::NotSupported("Memtable does not support snapshot"), nullptr);
4229 }
4230
4231 // Caller is not write thread, thus didn't provide a valid snapshot_seq.
4232 // Obtain seq from db.
4233 if (!need_update_seq) {
4234 snapshot_seq = GetLastPublishedSequence();
4235 }
4236
4237 std::shared_ptr<const SnapshotImpl> latest =
4238 timestamped_snapshots_.GetSnapshot(std::numeric_limits<uint64_t>::max());
4239
4240 // If there is already a latest timestamped snapshot, then we need to do
4241 // some checks.
4242 if (latest) {
4243 uint64_t latest_snap_ts = latest->GetTimestamp();
4244 SequenceNumber latest_snap_seq = latest->GetSequenceNumber();
4245 assert(latest_snap_seq <= snapshot_seq);
4246 bool needs_create_snap = true;
4247 Status status;
4248 std::shared_ptr<const SnapshotImpl> ret;
4249 if (latest_snap_ts > ts) {
4250 // A snapshot created later cannot have smaller timestamp than a
4251 // previous timestamped snapshot.
4252 needs_create_snap = false;
4253 std::ostringstream oss;
4254 oss << "snapshot exists with larger timestamp " << latest_snap_ts << " > "
4255 << ts;
4256 status = Status::InvalidArgument(oss.str());
4257 } else if (latest_snap_ts == ts) {
4258 if (latest_snap_seq == snapshot_seq) {
4259 // We are requesting the same sequence number and timestamp, thus can
4260 // safely reuse (share) the current latest timestamped snapshot.
4261 needs_create_snap = false;
4262 ret = latest;
4263 } else if (latest_snap_seq < snapshot_seq) {
4264 // There may have been writes to the database since the latest
4265 // timestamped snapshot, yet we are still requesting the same
4266 // timestamp. In this case, we cannot create the new timestamped
4267 // snapshot.
4268 needs_create_snap = false;
4269 std::ostringstream oss;
4270 oss << "Allocated seq is " << snapshot_seq
4271 << ", while snapshot exists with smaller seq " << latest_snap_seq
4272 << " but same timestamp " << ts;
4273 status = Status::InvalidArgument(oss.str());
4274 }
4275 }
4276 if (!needs_create_snap) {
4277 if (lock) {
4278 mutex_.Unlock();
4279 }
4280 delete s;
4281 return std::make_pair(status, ret);
4282 } else {
4283 status.PermitUncheckedError();
4284 }
4285 }
4286
4287 SnapshotImpl* snapshot =
4288 snapshots_.New(s, snapshot_seq, unix_time,
4289 /*is_write_conflict_boundary=*/true, ts);
4290
4291 std::shared_ptr<const SnapshotImpl> ret(
4292 snapshot,
4293 std::bind(&DBImpl::ReleaseSnapshot, this, std::placeholders::_1));
4295
4296 // Caller is from write thread, and we need to update database's sequence
4297 // number.
4298 if (need_update_seq) {
4299 assert(versions_);
4300 if (last_seq_same_as_publish_seq_) {
4301 versions_->SetLastSequence(snapshot_seq);
4302 } else {
4303 // TODO: support write-prepared/write-unprepared transactions with two
4304 // write queues.
4305 assert(false);
4306 }
4307 }
4308
4309 if (lock) {
4310 mutex_.Unlock();
4311 }
4312 return std::make_pair(Status::OK(), ret);
4313}
virtual SequenceNumber GetLastPublishedSequence() const
Definition db_impl.h:686
TimestampedSnapshotList timestamped_snapshots_
Definition db_impl.h:2802
SnapshotImpl * New(SnapshotImpl *s, SequenceNumber seq, uint64_t unix_time, bool is_write_conflict_boundary, uint64_t ts=std::numeric_limits< uint64_t >::max())
virtual Status GetCurrentTime(int64_t *unix_time)=0
void AddSnapshot(const std::shared_ptr< const SnapshotImpl > &snapshot)
std::shared_ptr< const SnapshotImpl > GetSnapshot(uint64_t ts) const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ CreateWAL()

IOStatus ROCKSDB_NAMESPACE::DBImpl::CreateWAL ( const WriteOptions & write_options,
uint64_t log_file_num,
uint64_t recycle_log_number,
size_t preallocate_block_size,
log::Writer ** new_log )
private

db_impl_open.cc 파일의 1958 번째 라인에서 정의되었습니다.

1961 {
1962 IOStatus io_s;
1963 std::unique_ptr<FSWritableFile> lfile;
1964
1965 DBOptions db_options =
1966 BuildDBOptions(immutable_db_options_, mutable_db_options_);
1967 FileOptions opt_file_options =
1968 fs_->OptimizeForLogWrite(file_options_, db_options);
1969 // DB option takes precedence when not kUnknown
1970 if (immutable_db_options_.wal_write_temperature != Temperature::kUnknown) {
1971 opt_file_options.temperature = immutable_db_options_.wal_write_temperature;
1972 }
1973 std::string wal_dir = immutable_db_options_.GetWalDir();
1974 std::string log_fname = LogFileName(wal_dir, log_file_num);
1975
1976 if (recycle_log_number) {
1978 "reusing log %" PRIu64 " from recycle list\n",
1979 recycle_log_number);
1980 std::string old_log_fname = LogFileName(wal_dir, recycle_log_number);
1981 TEST_SYNC_POINT("DBImpl::CreateWAL:BeforeReuseWritableFile1");
1982 TEST_SYNC_POINT("DBImpl::CreateWAL:BeforeReuseWritableFile2");
1983 io_s = fs_->ReuseWritableFile(log_fname, old_log_fname, opt_file_options,
1984 &lfile, /*dbg=*/nullptr);
1985 } else {
1986 io_s = NewWritableFile(fs_.get(), log_fname, &lfile, opt_file_options);
1987 }
1988
1989 if (io_s.ok()) {
1990 lfile->SetWriteLifeTimeHint(CalculateWALWriteHint());
1991 lfile->SetPreallocationBlockSize(preallocate_block_size);
1992
1993 const auto& listeners = immutable_db_options_.listeners;
1995 std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
1996 std::move(lfile), log_fname, opt_file_options,
1997 immutable_db_options_.clock, io_tracer_, nullptr /* stats */,
1998 Histograms::HISTOGRAM_ENUM_MAX /* hist_type */, listeners, nullptr,
1999 tmp_set.Contains(FileType::kWalFile),
2000 tmp_set.Contains(FileType::kWalFile)));
2001 *new_log = new log::Writer(std::move(file_writer), log_file_num,
2005 io_s = (*new_log)->AddCompressionTypeRecord(write_options);
2006 }
2007 return io_s;
2008}
Env::WriteLifeTimeHint CalculateWALWriteHint()
Definition db_impl.h:2466
SmallEnumSet< FileType, FileType::kBlobFile > FileTypeSet
Definition options.h:64
IOStatus NewWritableFile(FileSystem *fs, const std::string &fname, std::unique_ptr< FSWritableFile > *result, const FileOptions &options)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DefaultColumnFamily()

ColumnFamilyHandle * ROCKSDB_NAMESPACE::DBImpl::DefaultColumnFamily ( ) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 2152 번째 라인에서 정의되었습니다.

2152 {
2153 return default_cf_handle_;
2154}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DelayWrite()

Status ROCKSDB_NAMESPACE::DBImpl::DelayWrite ( uint64_t num_bytes,
WriteThread & write_thread,
const WriteOptions & write_options )
private

db_impl_write.cc 파일의 2098 번째 라인에서 정의되었습니다.

2099 {
2100 mutex_.AssertHeld();
2101 uint64_t start_time = 0;
2102 bool delayed = false;
2103 {
2104 // To avoid parallel timed delays (bad throttling), only support them
2105 // on the primary write queue.
2106 uint64_t delay;
2107 if (&write_thread == &write_thread_) {
2108 delay =
2110 } else {
2111 assert(num_bytes == 0);
2112 delay = 0;
2113 }
2114 TEST_SYNC_POINT("DBImpl::DelayWrite:Start");
2115 start_time = immutable_db_options_.clock->NowMicros();
2116
2117 if (delay > 0) {
2118 if (write_options.no_slowdown) {
2119 return Status::Incomplete("Write stall");
2120 }
2121 TEST_SYNC_POINT("DBImpl::DelayWrite:Sleep");
2122
2123 // Notify write_thread about the stall so it can setup a barrier and
2124 // fail any pending writers with no_slowdown
2125 write_thread.BeginWriteStall();
2126 mutex_.Unlock();
2127 TEST_SYNC_POINT("DBImpl::DelayWrite:BeginWriteStallDone");
2128 // We will delay the write until we have slept for `delay` microseconds
2129 // or we don't need a delay anymore. We check for cancellation every 1ms
2130 // (slightly longer because WriteController minimum delay is 1ms, in
2131 // case of sleep imprecision, rounding, etc.)
2132 const uint64_t kDelayInterval = 1001;
2133 uint64_t stall_end = start_time + delay;
2134 while (write_controller_.NeedsDelay()) {
2135 if (immutable_db_options_.clock->NowMicros() >= stall_end) {
2136 // We already delayed this write `delay` microseconds
2137 break;
2138 }
2139
2140 delayed = true;
2141 // Sleep for 0.001 seconds
2143 }
2144 mutex_.Lock();
2145 write_thread.EndWriteStall();
2146 }
2147
2148 // Don't wait if there's a background error that is not pending recovery
2149 // since recovery might never be attempted.
2150 while ((error_handler_.GetBGError().ok() ||
2153 !shutting_down_.load(std::memory_order_relaxed)) {
2154 if (write_options.no_slowdown) {
2155 return Status::Incomplete("Write stall");
2156 }
2157 delayed = true;
2158
2159 // Notify write_thread about the stall so it can setup a barrier and
2160 // fail any pending writers with no_slowdown
2161 write_thread.BeginWriteStall();
2162 if (&write_thread == &write_thread_) {
2163 TEST_SYNC_POINT("DBImpl::DelayWrite:Wait");
2164 } else {
2165 TEST_SYNC_POINT("DBImpl::DelayWrite:NonmemWait");
2166 }
2167 bg_cv_.Wait();
2168 TEST_SYNC_POINT_CALLBACK("DBImpl::DelayWrite:AfterWait", &mutex_);
2169 write_thread.EndWriteStall();
2170 }
2171 }
2172 assert(!delayed || !write_options.no_slowdown);
2173 if (delayed) {
2174 auto time_delayed = immutable_db_options_.clock->NowMicros() - start_time;
2176 InternalStats::kIntStatsWriteStallMicros, time_delayed);
2177 RecordTick(stats_, STALL_MICROS, time_delayed);
2178 RecordInHistogram(stats_, WRITE_STALL, time_delayed);
2179 }
2180
2181 // If DB is not in read-only mode and write_controller is not stopping
2182 // writes, we can ignore any background errors and allow the write to
2183 // proceed
2184 Status s;
2186 if (!shutting_down_.load(std::memory_order_relaxed)) {
2187 // If writes are still stopped and db not shutdown, it means we bailed
2188 // due to a background error
2189 s = Status::Incomplete(error_handler_.GetBGError().ToString());
2190 } else {
2191 s = Status::ShutdownInProgress("stalled writes");
2192 }
2193 }
2196 }
2197 return s;
2198}
std::string ToString() const
Definition status.cc:81
uint64_t GetDelay(SystemClock *clock, uint64_t num_bytes)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Delete() [1/4]

Status ROCKSDB_NAMESPACE::DBImpl::Delete ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 86 번째 라인에서 정의되었습니다.

87 {
88 const Status s = FailIfCfHasTs(column_family);
89 if (!s.ok()) {
90 return s;
91 }
92 return DB::Delete(write_options, column_family, key);
93}
Status FailIfCfHasTs(const ColumnFamilyHandle *column_family) const
Definition db_impl.h:3101
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Delete() [2/4]

Status ROCKSDB_NAMESPACE::DBImpl::Delete ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const Slice & ts )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 95 번째 라인에서 정의되었습니다.

97 {
98 const Status s = FailIfTsMismatchCf(column_family, ts);
99 if (!s.ok()) {
100 return s;
101 }
102 return DB::Delete(write_options, column_family, key, ts);
103}
Status FailIfTsMismatchCf(ColumnFamilyHandle *column_family, const Slice &ts) const
Definition db_impl.h:3118
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ Delete() [3/4]

virtual Status ROCKSDB_NAMESPACE::DB::Delete ( const WriteOptions & options,
const Slice & key )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 494 번째 라인에서 정의되었습니다.

494 {
495 return Delete(options, DefaultColumnFamily(), key);
496 }

◆ Delete() [4/4]

virtual Status ROCKSDB_NAMESPACE::DB::Delete ( const WriteOptions & options,
const Slice & key,
const Slice & ts )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 497 번째 라인에서 정의되었습니다.

498 {
499 return Delete(options, DefaultColumnFamily(), key, ts);
500 }

◆ DeleteAllRecoveredTransactions()

void ROCKSDB_NAMESPACE::DBImpl::DeleteAllRecoveredTransactions ( )
inline

db_impl.h 파일의 1047 번째 라인에서 정의되었습니다.

1047 {
1048 for (auto it = recovered_transactions_.begin();
1049 it != recovered_transactions_.end(); ++it) {
1050 delete it->second;
1051 }
1053 }
std::unordered_map< std::string, RecoveredTransaction * > recovered_transactions_
Definition db_impl.h:1358

◆ DeleteFile()

Status ROCKSDB_NAMESPACE::DBImpl::DeleteFile ( std::string name)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4881 번째 라인에서 정의되었습니다.

4881 {
4882 // TODO: plumb Env::IOActivity, Env::IOPriority
4883 const ReadOptions read_options;
4884 const WriteOptions write_options;
4885
4886 uint64_t number;
4887 FileType type;
4888 WalFileType log_type;
4889 if (!ParseFileName(name, &number, &type, &log_type) ||
4890 (type != kTableFile && type != kWalFile)) {
4891 ROCKS_LOG_ERROR(immutable_db_options_.info_log, "DeleteFile %s failed.\n",
4892 name.c_str());
4893 return Status::InvalidArgument("Invalid file name");
4894 }
4895
4896 if (type == kWalFile) {
4897 // Only allow deleting archived log files
4898 if (log_type != kArchivedLogFile) {
4900 "DeleteFile %s failed - not archived log.\n",
4901 name.c_str());
4902 return Status::NotSupported("Delete only supported for archived logs");
4903 }
4904 Status status = wal_manager_.DeleteFile(name, number);
4905 if (!status.ok()) {
4907 "DeleteFile %s failed -- %s.\n", name.c_str(),
4908 status.ToString().c_str());
4909 }
4910 return status;
4911 }
4912
4913 Status status;
4914 int level;
4915 FileMetaData* metadata;
4916 ColumnFamilyData* cfd;
4917 VersionEdit edit;
4918 JobContext job_context(next_job_id_.fetch_add(1), true);
4919 {
4920 InstrumentedMutexLock l(&mutex_);
4921 status = versions_->GetMetadataForFile(number, &level, &metadata, &cfd);
4922 if (!status.ok()) {
4924 "DeleteFile %s failed. File not found\n", name.c_str());
4925 job_context.Clean();
4926 return Status::InvalidArgument("File not found");
4927 }
4928 assert(level < cfd->NumberLevels());
4929
4930 // If the file is being compacted no need to delete.
4931 if (metadata->being_compacted) {
4933 "DeleteFile %s Skipped. File about to be compacted\n",
4934 name.c_str());
4935 job_context.Clean();
4936 return Status::OK();
4937 }
4938
4939 // Only the files in the last level can be deleted externally.
4940 // This is to make sure that any deletion tombstones are not
4941 // lost. Check that the level passed is the last level.
4942 auto* vstoreage = cfd->current()->storage_info();
4943 for (int i = level + 1; i < cfd->NumberLevels(); i++) {
4944 if (vstoreage->NumLevelFiles(i) != 0) {
4946 "DeleteFile %s FAILED. File not in last level\n",
4947 name.c_str());
4948 job_context.Clean();
4949 return Status::InvalidArgument("File not in last level");
4950 }
4951 }
4952 // if level == 0, it has to be the oldest file
4953 if (level == 0 &&
4954 vstoreage->LevelFiles(0).back()->fd.GetNumber() != number) {
4956 "DeleteFile %s failed ---"
4957 " target file in level 0 must be the oldest.",
4958 name.c_str());
4959 job_context.Clean();
4960 return Status::InvalidArgument("File in level 0, but not oldest");
4961 }
4962 edit.SetColumnFamily(cfd->GetID());
4963 edit.DeleteFile(level, number);
4964 status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
4965 read_options, write_options, &edit, &mutex_,
4967 if (status.ok()) {
4969 cfd, job_context.superversion_contexts.data(),
4970 *cfd->GetLatestMutableCFOptions());
4971 }
4972 FindObsoleteFiles(&job_context, false);
4973 } // lock released here
4974
4976 // remove files outside the db-lock
4977 if (job_context.HaveSomethingToDelete()) {
4978 // Call PurgeObsoleteFiles() without holding mutex.
4979 PurgeObsoleteFiles(job_context);
4980 }
4981 job_context.Clean();
4982 return status;
4983}
int NumberLevels(ColumnFamilyHandle *column_family) override
Status DeleteFile(const std::string &fname, uint64_t number)
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type, WalFileType *log_type)
Definition filename.cc:268
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteFilesInRanges()

Status ROCKSDB_NAMESPACE::DBImpl::DeleteFilesInRanges ( ColumnFamilyHandle * column_family,
const RangePtr * ranges,
size_t n,
bool include_end = true )

db_impl.cc 파일의 4985 번째 라인에서 정의되었습니다.

4987 {
4988 // TODO: plumb Env::IOActivity, Env::IOPriority
4989 const ReadOptions read_options;
4990 const WriteOptions write_options;
4991
4992 Status status = Status::OK();
4993 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
4994 ColumnFamilyData* cfd = cfh->cfd();
4995 const Comparator* ucmp = cfd->user_comparator();
4996 assert(ucmp);
4997 const size_t ts_sz = ucmp->timestamp_size();
4998 autovector<UserKeyRangePtr> ukey_ranges;
4999 std::vector<std::string> keys;
5000 std::vector<Slice> key_slices;
5001 ukey_ranges.reserve(n);
5002 keys.reserve(2 * n);
5003 key_slices.reserve(2 * n);
5004 for (size_t i = 0; i < n; i++) {
5005 auto [start, limit] = MaybeAddTimestampsToRange(
5006 ranges[i].start, ranges[i].limit, ts_sz, &keys.emplace_back(),
5007 &keys.emplace_back(), !include_end);
5008 assert((ranges[i].start != nullptr) == start.has_value());
5009 assert((ranges[i].limit != nullptr) == limit.has_value());
5010 ukey_ranges.emplace_back(start, limit);
5011 }
5012
5013 VersionEdit edit;
5014 std::set<FileMetaData*> deleted_files;
5015 JobContext job_context(next_job_id_.fetch_add(1), true);
5016 {
5017 InstrumentedMutexLock l(&mutex_);
5018 Version* input_version = cfd->current();
5019
5020 auto* vstorage = input_version->storage_info();
5021 for (const auto& range : ukey_ranges) {
5022 auto begin = range.start.has_value() ? &range.start.value() : nullptr;
5023 auto end = range.limit.has_value() ? &range.limit.value() : nullptr;
5024 for (int i = 1; i < cfd->NumberLevels(); i++) {
5025 if (vstorage->LevelFiles(i).empty() ||
5026 !vstorage->OverlapInLevel(i, begin, end)) {
5027 continue;
5028 }
5029 std::vector<FileMetaData*> level_files;
5030 InternalKey begin_storage, end_storage, *begin_key, *end_key;
5031 if (begin == nullptr) {
5032 begin_key = nullptr;
5033 } else {
5034 begin_storage.SetMinPossibleForUserKey(*begin);
5035 begin_key = &begin_storage;
5036 }
5037 if (end == nullptr) {
5038 end_key = nullptr;
5039 } else {
5040 end_storage.SetMaxPossibleForUserKey(*end);
5041 end_key = &end_storage;
5042 }
5043
5044 vstorage->GetCleanInputsWithinInterval(
5045 i, begin_key, end_key, &level_files, -1 /* hint_index */,
5046 nullptr /* file_index */);
5047 FileMetaData* level_file;
5048 for (uint32_t j = 0; j < level_files.size(); j++) {
5049 level_file = level_files[j];
5050 if (level_file->being_compacted) {
5051 continue;
5052 }
5053 if (deleted_files.find(level_file) != deleted_files.end()) {
5054 continue;
5055 }
5056 if (!include_end && end != nullptr &&
5057 (ucmp->CompareWithoutTimestamp(level_file->largest.user_key(),
5058 *end) == 0)) {
5059 continue;
5060 }
5061 edit.SetColumnFamily(cfd->GetID());
5062 edit.DeleteFile(i, level_file->fd.GetNumber());
5063 deleted_files.insert(level_file);
5064 level_file->being_compacted = true;
5065 }
5066 }
5067 }
5068 if (!deleted_files.empty()) {
5069 vstorage->ComputeCompactionScore(*cfd->ioptions(),
5070 *cfd->GetLatestMutableCFOptions());
5071 }
5072 if (edit.GetDeletedFiles().empty()) {
5073 job_context.Clean();
5074 return status;
5075 }
5076 input_version->Ref();
5077 status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
5078 read_options, write_options, &edit, &mutex_,
5080 if (status.ok()) {
5082 cfd, job_context.superversion_contexts.data(),
5083 *cfd->GetLatestMutableCFOptions());
5084 }
5085 for (auto* deleted_file : deleted_files) {
5086 deleted_file->being_compacted = false;
5087 }
5088 input_version->Unref();
5089 FindObsoleteFiles(&job_context, false);
5090 } // lock released here
5091
5093 // remove files outside the db-lock
5094 if (job_context.HaveSomethingToDelete()) {
5095 // Call PurgeObsoleteFiles() without holding mutex.
5096 PurgeObsoleteFiles(job_context);
5097 }
5098 job_context.Clean();
5099 return status;
5100}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteObsoleteFileImpl()

void ROCKSDB_NAMESPACE::DBImpl::DeleteObsoleteFileImpl ( int job_id,
const std::string & fname,
const std::string & path_to_sync,
FileType type,
uint64_t number )
private

db_impl_files.cc 파일의 365 번째 라인에서 정의되었습니다.

367 {
368 TEST_SYNC_POINT_CALLBACK("DBImpl::DeleteObsoleteFileImpl::BeforeDeletion",
369 const_cast<std::string*>(&fname));
370
371 Status file_deletion_status;
372 if (type == kTableFile || type == kBlobFile || type == kWalFile) {
373 // Rate limit WAL deletion only if its in the DB dir
374 file_deletion_status = DeleteDBFile(
375 &immutable_db_options_, fname, path_to_sync,
376 /*force_bg=*/false,
377 /*force_fg=*/(type == kWalFile) ? !wal_in_db_path_ : false);
378 } else {
379 file_deletion_status = env_->DeleteFile(fname);
380 }
381 TEST_SYNC_POINT_CALLBACK("DBImpl::DeleteObsoleteFileImpl:AfterDeletion",
382 &file_deletion_status);
383 if (file_deletion_status.ok()) {
385 "[JOB %d] Delete %s type=%d #%" PRIu64 " -- %s\n", job_id,
386 fname.c_str(), type, number,
387 file_deletion_status.ToString().c_str());
388 } else if (env_->FileExists(fname).IsNotFound()) {
391 "[JOB %d] Tried to delete a non-existing file %s type=%d #%" PRIu64
392 " -- %s\n",
393 job_id, fname.c_str(), type, number,
394 file_deletion_status.ToString().c_str());
395 } else {
397 "[JOB %d] Failed to delete %s type=%d #%" PRIu64 " -- %s\n",
398 job_id, fname.c_str(), type, number,
399 file_deletion_status.ToString().c_str());
400 }
401 if (type == kTableFile) {
402 EventHelpers::LogAndNotifyTableFileDeletion(
403 &event_logger_, job_id, number, fname, file_deletion_status, GetName(),
405 }
406 if (type == kBlobFile) {
407 EventHelpers::LogAndNotifyBlobFileDeletion(
408 &event_logger_, immutable_db_options_.listeners, job_id, number, fname,
409 file_deletion_status, GetName());
410 }
411}
const std::string & GetName() const override
Definition db_impl.cc:4466
virtual Status DeleteFile(const std::string &fname)=0
virtual Status FileExists(const std::string &fname)=0
bool IsNotFound() const
Definition status.h:340
#define ROCKS_LOG_DEBUG(LGR, FMT,...)
Definition logging.h:35
Status DeleteDBFile(const ImmutableDBOptions *db_options, const std::string &fname, const std::string &dir_to_sync, const bool force_bg, const bool force_fg)
Definition file_util.cc:125
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteObsoleteFiles()

void ROCKSDB_NAMESPACE::DBImpl::DeleteObsoleteFiles ( )
private

db_impl_files.cc 파일의 727 번째 라인에서 정의되었습니다.

727 {
728 mutex_.AssertHeld();
729 JobContext job_context(next_job_id_.fetch_add(1));
730 FindObsoleteFiles(&job_context, true);
731
732 mutex_.Unlock();
733 if (job_context.HaveSomethingToDelete()) {
735 PurgeObsoleteFiles(job_context, defer_purge);
736 }
737 job_context.Clean();
738 mutex_.Lock();
739}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteObsoleteOptionsFiles()

Status ROCKSDB_NAMESPACE::DBImpl::DeleteObsoleteOptionsFiles ( )
protected

db_impl.cc 파일의 5593 번째 라인에서 정의되었습니다.

5593 {
5594 std::vector<std::string> filenames;
5595 // use ordered map to store keep the filenames sorted from the newest
5596 // to the oldest.
5597 std::map<uint64_t, std::string> options_filenames;
5598 Status s;
5599 IOOptions io_opts;
5600 io_opts.do_not_recurse = true;
5601 s = fs_->GetChildren(GetName(), io_opts, &filenames,
5602 /*IODebugContext*=*/nullptr);
5603 if (!s.ok()) {
5604 return s;
5605 }
5606 for (auto& filename : filenames) {
5607 uint64_t file_number;
5608 FileType type;
5609 if (ParseFileName(filename, &file_number, &type) && type == kOptionsFile) {
5610 options_filenames.insert(
5611 {std::numeric_limits<uint64_t>::max() - file_number,
5612 GetName() + "/" + filename});
5613 }
5614 }
5615
5616 // Keeps the latest 2 Options file
5617 const size_t kNumOptionsFilesKept = 2;
5618 DeleteOptionsFilesHelper(options_filenames, kNumOptionsFilesKept,
5620 return Status::OK();
5621}
Env * GetEnv() const override
Definition db_impl.cc:4468
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteRange() [1/4]

Status ROCKSDB_NAMESPACE::DBImpl::DeleteRange ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & begin_key,
const Slice & end_key )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl_write.cc 파일의 125 번째 라인에서 정의되었습니다.

127 {
128 const Status s = FailIfCfHasTs(column_family);
129 if (!s.ok()) {
130 return s;
131 }
132 return DB::DeleteRange(write_options, column_family, begin_key, end_key);
133}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteRange() [2/4]

Status ROCKSDB_NAMESPACE::DBImpl::DeleteRange ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & begin_key,
const Slice & end_key,
const Slice & ts )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl_write.cc 파일의 135 번째 라인에서 정의되었습니다.

138 {
139 const Status s = FailIfTsMismatchCf(column_family, ts);
140 if (!s.ok()) {
141 return s;
142 }
143 return DB::DeleteRange(write_options, column_family, begin_key, end_key, ts);
144}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteRange() [3/4]

virtual Status ROCKSDB_NAMESPACE::DB::DeleteRange ( const WriteOptions & options,
const Slice & begin_key,
const Slice & end_key )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 555 번째 라인에서 정의되었습니다.

556 {
557 return DeleteRange(options, DefaultColumnFamily(), begin_key, end_key);
558 }

◆ DeleteRange() [4/4]

virtual Status ROCKSDB_NAMESPACE::DB::DeleteRange ( const WriteOptions & options,
const Slice & begin_key,
const Slice & end_key,
const Slice & ts )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 559 번째 라인에서 정의되었습니다.

561 {
562 return DeleteRange(options, DefaultColumnFamily(), begin_key, end_key, ts);
563 }

◆ DeleteRecoveredTransaction()

void ROCKSDB_NAMESPACE::DBImpl::DeleteRecoveredTransaction ( const std::string & name)
inline

db_impl.h 파일의 1035 번째 라인에서 정의되었습니다.

1035 {
1036 auto it = recovered_transactions_.find(name);
1037 assert(it != recovered_transactions_.end());
1038 auto* trx = it->second;
1039 recovered_transactions_.erase(it);
1040 for (const auto& info : trx->batches_) {
1042 info.second.log_number_);
1043 }
1044 delete trx;
1045 }
LogsWithPrepTracker logs_with_prep_tracker_
Definition db_impl.h:2947

◆ DisableFileDeletions()

Status ROCKSDB_NAMESPACE::DBImpl::DisableFileDeletions ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_files.cc 파일의 54 번째 라인에서 정의되었습니다.

54 {
55 Status s;
56 int my_disable_delete_obsolete_files;
57 {
58 InstrumentedMutexLock l(&mutex_);
60 my_disable_delete_obsolete_files = disable_delete_obsolete_files_;
61 }
62 if (my_disable_delete_obsolete_files == 1) {
63 ROCKS_LOG_INFO(immutable_db_options_.info_log, "File Deletions Disabled");
64 } else {
66 "File Deletions Disabled, but already disabled. Counter: %d",
67 my_disable_delete_obsolete_files);
68 }
69 return s;
70}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DisableFileDeletionsWithLock()

Status ROCKSDB_NAMESPACE::DBImpl::DisableFileDeletionsWithLock ( )
private

db_impl_files.cc 파일의 74 번째 라인에서 정의되었습니다.

74 {
75 mutex_.AssertHeld();
77 return Status::OK();
78}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DisableManualCompaction()

void ROCKSDB_NAMESPACE::DBImpl::DisableManualCompaction ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 2807 번째 라인에서 정의되었습니다.

2807 {
2808 InstrumentedMutexLock l(&mutex_);
2809 manual_compaction_paused_.fetch_add(1, std::memory_order_release);
2810
2811 // Mark the canceled as true when the cancellation is triggered by
2812 // manual_compaction_paused (may overwrite user-provided `canceled`)
2813 for (const auto& manual_compaction : manual_compaction_dequeue_) {
2814 manual_compaction->canceled = true;
2815 }
2816
2817 // Wake up manual compactions waiting to start.
2818 bg_cv_.SignalAll();
2819
2820 // Wait for any pending manual compactions to finish (typically through
2821 // failing with `Status::Incomplete`) prior to returning. This way we are
2822 // guaranteed no pending manual compaction will commit while manual
2823 // compactions are "disabled".
2824 while (HasPendingManualCompaction()) {
2825 bg_cv_.Wait();
2826 }
2827}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DropColumnFamilies()

Status ROCKSDB_NAMESPACE::DBImpl::DropColumnFamilies ( const std::vector< ColumnFamilyHandle * > & column_families)
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 3702 번째 라인에서 정의되었습니다.

3703 {
3704 InstrumentedMutexLock ol(&options_mutex_);
3705 Status s;
3706 bool success_once = false;
3707 for (auto* handle : column_families) {
3708 s = DropColumnFamilyImpl(handle);
3709 if (!s.ok()) {
3710 break;
3711 }
3712 success_once = true;
3713 }
3714 if (success_once) {
3715 // TODO: plumb Env::IOActivity, Env::IOPriority
3716 Status persist_options_status =
3717 WriteOptionsFile(WriteOptions(), false /*db_mutex_already_held*/);
3718 if (s.ok() && !persist_options_status.ok()) {
3719 s = persist_options_status;
3720 }
3721 }
3722 return s;
3723}
Status WriteOptionsFile(const WriteOptions &write_options, bool db_mutex_already_held)
Definition db_impl.cc:5506
Status DropColumnFamilyImpl(ColumnFamilyHandle *column_family)
Definition db_impl.cc:3725
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DropColumnFamily()

Status ROCKSDB_NAMESPACE::DBImpl::DropColumnFamily ( ColumnFamilyHandle * column_family)
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 3691 번째 라인에서 정의되었습니다.

3691 {
3692 assert(column_family != nullptr);
3693 InstrumentedMutexLock ol(&options_mutex_);
3694 Status s = DropColumnFamilyImpl(column_family);
3695 if (s.ok()) {
3696 // TODO: plumb Env::IOActivity, Env::IOPriority
3697 s = WriteOptionsFile(WriteOptions(), false /*db_mutex_already_held*/);
3698 }
3699 return s;
3700}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DropColumnFamilyImpl()

Status ROCKSDB_NAMESPACE::DBImpl::DropColumnFamilyImpl ( ColumnFamilyHandle * column_family)
private

db_impl.cc 파일의 3725 번째 라인에서 정의되었습니다.

3725 {
3727
3728 // TODO: plumb Env::IOActivity, Env::IOPriority
3729 const ReadOptions read_options;
3730 const WriteOptions write_options;
3731
3732 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
3733 auto cfd = cfh->cfd();
3734 if (cfd->GetID() == 0) {
3735 return Status::InvalidArgument("Can't drop default column family");
3736 }
3737
3738 bool cf_support_snapshot = cfd->mem()->IsSnapshotSupported();
3739
3740 VersionEdit edit;
3741 edit.DropColumnFamily();
3742 edit.SetColumnFamily(cfd->GetID());
3743
3744 Status s;
3745 // Save re-aquiring lock for RegisterRecordSeqnoTimeWorker when not
3746 // applicable
3747 bool used_preserve_preclude = false;
3748 {
3749 InstrumentedMutexLock l(&mutex_);
3750 if (cfd->IsDropped()) {
3751 s = Status::InvalidArgument("Column family already dropped!\n");
3752 }
3753 if (s.ok()) {
3754 // we drop column family from a single write thread
3755 WriteThread::Writer w;
3756 write_thread_.EnterUnbatched(&w, &mutex_);
3757 s = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
3758 read_options, write_options, &edit, &mutex_,
3761 }
3762 if (s.ok()) {
3763 auto& moptions = *cfd->GetLatestMutableCFOptions();
3765 moptions.write_buffer_size * moptions.max_write_buffer_number;
3766 used_preserve_preclude = moptions.preserve_internal_time_seconds > 0 ||
3767 moptions.preclude_last_level_data_seconds > 0;
3768 }
3769
3770 if (!cf_support_snapshot) {
3771 // Dropped Column Family doesn't support snapshot. Need to recalculate
3772 // is_snapshot_supported_.
3773 bool new_is_snapshot_supported = true;
3774 for (auto c : *versions_->GetColumnFamilySet()) {
3775 if (!c->IsDropped() && !c->mem()->IsSnapshotSupported()) {
3776 new_is_snapshot_supported = false;
3777 break;
3778 }
3779 }
3780 is_snapshot_supported_ = new_is_snapshot_supported;
3781 }
3782 bg_cv_.SignalAll();
3783 }
3784
3785 if (used_preserve_preclude) {
3786 s = RegisterRecordSeqnoTimeWorker(read_options, write_options,
3787 /* is_new_db */ false);
3788 }
3789
3790 if (s.ok()) {
3791 // Note that here we erase the associated cf_info of the to-be-dropped
3792 // cfd before its ref-count goes to zero to avoid having to erase cf_info
3793 // later inside db_mutex.
3795 assert(cfd->IsDropped());
3797 "Dropped column family with id %u\n", cfd->GetID());
3798 } else {
3800 "Dropping column family with id %u FAILED -- %s\n",
3801 cfd->GetID(), s.ToString().c_str());
3802 }
3803
3804 return s;
3805}
void EraseThreadStatusCfInfo(ColumnFamilyData *cfd) const
Definition db_impl.cc:5701
Status RegisterRecordSeqnoTimeWorker(const ReadOptions &read_options, const WriteOptions &write_options, bool is_new_db)
Definition db_impl.cc:843
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DumpStats()

void ROCKSDB_NAMESPACE::DBImpl::DumpStats ( )

db_impl.cc 파일의 1152 번째 라인에서 정의되었습니다.

1152 {
1153 TEST_SYNC_POINT("DBImpl::DumpStats:1");
1154 std::string stats;
1155 if (shutdown_initiated_) {
1156 return;
1157 }
1158
1159 // Also probe block cache(s) for problems, dump to info log
1160 UnorderedSet<Cache*> probed_caches;
1161 TEST_SYNC_POINT("DBImpl::DumpStats:StartRunning");
1162 {
1163 InstrumentedMutexLock l(&mutex_);
1164 for (auto cfd : versions_->GetRefedColumnFamilySet()) {
1165 if (!cfd->initialized()) {
1166 continue;
1167 }
1168
1169 auto* table_factory =
1170 cfd->GetCurrentMutableCFOptions()->table_factory.get();
1171 assert(table_factory != nullptr);
1172 // FIXME: need to a shared_ptr if/when block_cache is going to be mutable
1173 Cache* cache =
1174 table_factory->GetOptions<Cache>(TableFactory::kBlockCacheOpts());
1175
1176 // Release DB mutex for gathering cache entry stats. Pass over all
1177 // column families for this first so that other stats are dumped
1178 // near-atomically.
1179 InstrumentedMutexUnlock u(&mutex_);
1180 cfd->internal_stats()->CollectCacheEntryStats(/*foreground=*/false);
1181
1182 // Probe block cache for problems (if not already via another CF)
1184 if (cache && probed_caches.insert(cache).second) {
1185 cache->ReportProblems(immutable_db_options_.info_log);
1186 }
1187 }
1188 }
1189
1190 const std::string* property = &DB::Properties::kDBStats;
1191 const DBPropertyInfo* property_info = GetPropertyInfo(*property);
1192 assert(property_info != nullptr);
1193 assert(!property_info->need_out_of_mutex);
1194 default_cf_internal_stats_->GetStringProperty(*property_info, *property,
1195 &stats);
1196
1197 property = &InternalStats::kPeriodicCFStats;
1198 property_info = GetPropertyInfo(*property);
1199 assert(property_info != nullptr);
1200 assert(!property_info->need_out_of_mutex);
1201 for (auto cfd : *versions_->GetColumnFamilySet()) {
1202 if (cfd->initialized()) {
1203 cfd->internal_stats()->GetStringProperty(*property_info, *property,
1204 &stats);
1205 }
1206 }
1207 }
1208 TEST_SYNC_POINT("DBImpl::DumpStats:2");
1210 "------- DUMPING STATS -------");
1211 ROCKS_LOG_INFO(immutable_db_options_.info_log, "%s", stats.c_str());
1213 stats.clear();
1214 DumpMallocStats(&stats);
1215 if (!stats.empty()) {
1217 "------- Malloc STATS -------");
1218 ROCKS_LOG_INFO(immutable_db_options_.info_log, "%s", stats.c_str());
1219 }
1220 }
1221
1223}
bool GetStringProperty(const DBPropertyInfo &property_info, const Slice &property, std::string *value)
const DBPropertyInfo * GetPropertyInfo(const Slice &property)
void DumpMallocStats(std::string *)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnableAutoCompaction()

Status ROCKSDB_NAMESPACE::DBImpl::EnableAutoCompaction ( const std::vector< ColumnFamilyHandle * > & column_family_handles)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 2791 번째 라인에서 정의되었습니다.

2792 {
2793 Status s;
2794 for (auto cf_ptr : column_family_handles) {
2795 Status status =
2796 this->SetOptions(cf_ptr, {{"disable_auto_compactions", "false"}});
2797 if (!status.ok()) {
2798 s = status;
2799 }
2800 }
2801
2802 return s;
2803}
Status SetOptions(ColumnFamilyHandle *column_family, const std::unordered_map< std::string, std::string > &options_map) override
Definition db_impl.cc:1272
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnableFileDeletions()

Status ROCKSDB_NAMESPACE::DBImpl::EnableFileDeletions ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_files.cc 파일의 80 번째 라인에서 정의되었습니다.

80 {
81 // Job id == 0 means that this is not our background process, but rather
82 // user thread
83 JobContext job_context(0);
84 int saved_counter; // initialize on all paths
85 {
86 InstrumentedMutexLock l(&mutex_);
87 if (disable_delete_obsolete_files_ > 0) {
89 }
90 saved_counter = disable_delete_obsolete_files_;
91 if (saved_counter == 0) {
92 FindObsoleteFiles(&job_context, true);
94 }
95 }
96 if (saved_counter == 0) {
97 ROCKS_LOG_INFO(immutable_db_options_.info_log, "File Deletions Enabled");
98 if (job_context.HaveSomethingToDelete()) {
99 PurgeObsoleteFiles(job_context);
100 }
101 } else {
103 "File Deletions Enable, but not really enabled. Counter: %d",
104 saved_counter);
105 }
106 job_context.Clean();
108 return Status::OK();
109}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnableManualCompaction()

void ROCKSDB_NAMESPACE::DBImpl::EnableManualCompaction ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 2834 번째 라인에서 정의되었습니다.

2834 {
2835 InstrumentedMutexLock l(&mutex_);
2836 assert(manual_compaction_paused_ > 0);
2837 manual_compaction_paused_.fetch_sub(1, std::memory_order_release);
2838}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EndBlockCacheTrace()

Status ROCKSDB_NAMESPACE::DBImpl::EndBlockCacheTrace ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6711 번째 라인에서 정의되었습니다.

6711 {
6713 return Status::OK();
6714}
BlockCacheTracer block_cache_tracer_
Definition db_impl.h:1361
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EndIOTrace()

Status ROCKSDB_NAMESPACE::DBImpl::EndIOTrace ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 4490 번째 라인에서 정의되었습니다.

4490 {
4491 io_tracer_->EndIOTrace();
4492 return Status::OK();
4493}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EndTrace()

Status ROCKSDB_NAMESPACE::DBImpl::EndTrace ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6668 번째 라인에서 정의되었습니다.

6668 {
6669 InstrumentedMutexLock lock(&trace_mutex_);
6670 Status s;
6671 if (tracer_ != nullptr) {
6672 s = tracer_->Close();
6673 tracer_.reset();
6674 } else {
6675 s = Status::IOError("No trace file to close");
6676 }
6677 return s;
6678}
std::unique_ptr< Tracer > tracer_
Definition db_impl.h:1359
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnoughRoomForCompaction()

bool ROCKSDB_NAMESPACE::DBImpl::EnoughRoomForCompaction ( ColumnFamilyData * cfd,
const std::vector< CompactionInputFiles > & inputs,
bool * sfm_bookkeeping,
LogBuffer * log_buffer )
private

db_impl_compaction_flush.cc 파일의 34 번째 라인에서 정의되었습니다.

36 {
37 // Check if we have enough room to do the compaction
38 bool enough_room = true;
39 auto sfm = static_cast<SstFileManagerImpl*>(
41 if (sfm) {
42 // Pass the current bg_error_ to SFM so it can decide what checks to
43 // perform. If this DB instance hasn't seen any error yet, the SFM can be
44 // optimistic and not do disk space checks
45 Status bg_error = error_handler_.GetBGError();
46 enough_room = sfm->EnoughRoomForCompaction(cfd, inputs, bg_error);
47 bg_error.PermitUncheckedError(); // bg_error is just a copy of the Status
48 // from the error_handler_
49 if (enough_room) {
50 *sfm_reserved_compact_space = true;
51 }
52 }
53 if (!enough_room) {
54 // Just in case tests want to change the value of enough_room
56 "DBImpl::BackgroundCompaction():CancelledCompaction", &enough_room);
57 ROCKS_LOG_BUFFER(log_buffer,
58 "Cancelled compaction because not enough room");
59 RecordTick(stats_, COMPACTION_CANCELLED, 1);
60 }
61 return enough_room;
62}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnqueuePendingCompaction()

void ROCKSDB_NAMESPACE::DBImpl::EnqueuePendingCompaction ( ColumnFamilyData * cfd)
private

db_impl_compaction_flush.cc 파일의 3061 번째 라인에서 정의되었습니다.

3061 {
3062 mutex_.AssertHeld();
3063 if (reject_new_background_jobs_) {
3064 return;
3065 }
3066 if (!cfd->queued_for_compaction() && cfd->NeedsCompaction()) {
3067 TEST_SYNC_POINT_CALLBACK("EnqueuePendingCompaction::cfd",
3068 static_cast<void*>(cfd));
3070 }
3071}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnqueuePendingFlush()

bool ROCKSDB_NAMESPACE::DBImpl::EnqueuePendingFlush ( const FlushRequest & req)
private

db_impl_compaction_flush.cc 파일의 3025 번째 라인에서 정의되었습니다.

3025 {
3026 mutex_.AssertHeld();
3027 bool enqueued = false;
3028 if (reject_new_background_jobs_) {
3029 return enqueued;
3030 }
3031 if (flush_req.cfd_to_max_mem_id_to_persist.empty()) {
3032 return enqueued;
3033 }
3035 // For the non-atomic flush case, we never schedule multiple column
3036 // families in the same flush request.
3037 assert(flush_req.cfd_to_max_mem_id_to_persist.size() == 1);
3038 ColumnFamilyData* cfd =
3039 flush_req.cfd_to_max_mem_id_to_persist.begin()->first;
3040 assert(cfd);
3041
3042 if (!cfd->queued_for_flush() && cfd->imm()->IsFlushPending()) {
3043 cfd->Ref();
3044 cfd->set_queued_for_flush(true);
3046 flush_queue_.push_back(flush_req);
3047 enqueued = true;
3048 }
3049 } else {
3050 for (auto& iter : flush_req.cfd_to_max_mem_id_to_persist) {
3051 ColumnFamilyData* cfd = iter.first;
3052 cfd->Ref();
3053 }
3055 flush_queue_.push_back(flush_req);
3056 enqueued = true;
3057 }
3058 return enqueued;
3059}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EraseThreadStatusCfInfo()

void ROCKSDB_NAMESPACE::DBImpl::EraseThreadStatusCfInfo ( ColumnFamilyData * cfd) const
protected

db_impl.cc 파일의 5701 번째 라인에서 정의되었습니다.

5701{}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EraseThreadStatusDbInfo()

void ROCKSDB_NAMESPACE::DBImpl::EraseThreadStatusDbInfo ( ) const
protected

db_impl.cc 파일의 5703 번째 라인에서 정의되었습니다.

5703{}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EstimateInMemoryStatsHistorySize()

size_t ROCKSDB_NAMESPACE::DBImpl::EstimateInMemoryStatsHistorySize ( ) const
private

db_impl.cc 파일의 986 번째 라인에서 정의되었습니다.

986 {
988 size_t size_total =
989 sizeof(std::map<uint64_t, std::map<std::string, uint64_t>>);
990 if (stats_history_.size() == 0) {
991 return size_total;
992 }
993 size_t size_per_slice =
994 sizeof(uint64_t) + sizeof(std::map<std::string, uint64_t>);
995 // non-empty map, stats_history_.begin() guaranteed to exist
996 for (const auto& pairs : stats_history_.begin()->second) {
997 size_per_slice +=
998 pairs.first.capacity() + sizeof(pairs.first) + sizeof(pairs.second);
999 }
1000 size_total = size_per_slice * stats_history_.size();
1001 return size_total;
1002}
std::map< uint64_t, std::map< std::string, uint64_t > > stats_history_
Definition db_impl.h:2772
InstrumentedMutex stats_history_mutex_
Definition db_impl.h:2607
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FailIfCfHasTs()

Status ROCKSDB_NAMESPACE::DBImpl::FailIfCfHasTs ( const ColumnFamilyHandle * column_family) const
inlineprotected

db_impl.h 파일의 3101 번째 라인에서 정의되었습니다.

3102 {
3103 if (!column_family) {
3104 return Status::InvalidArgument("column family handle cannot be null");
3105 }
3106 assert(column_family);
3107 const Comparator* const ucmp = column_family->GetComparator();
3108 assert(ucmp);
3109 if (ucmp->timestamp_size() > 0) {
3110 std::ostringstream oss;
3111 oss << "cannot call this method on column family "
3112 << column_family->GetName() << " that enables timestamp";
3113 return Status::InvalidArgument(oss.str());
3114 }
3115 return Status::OK();
3116}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FailIfReadCollapsedHistory()

Status ROCKSDB_NAMESPACE::DBImpl::FailIfReadCollapsedHistory ( const ColumnFamilyData * cfd,
const SuperVersion * sv,
const Slice & ts ) const
inlineprotected

db_impl.h 파일의 3142 번째 라인에서 정의되었습니다.

3144 {
3145 // Reaching to this point means the timestamp size matching sanity check in
3146 // `DBImpl::FailIfTsMismatchCf` already passed. So we skip that and assume
3147 // column family has the same user-defined timestamp format as `ts`.
3148 const Comparator* const ucmp = cfd->user_comparator();
3149 assert(ucmp);
3150 const std::string& full_history_ts_low = sv->full_history_ts_low;
3151 assert(full_history_ts_low.empty() ||
3152 full_history_ts_low.size() == ts.size());
3153 if (!full_history_ts_low.empty() &&
3154 ucmp->CompareTimestamp(ts, full_history_ts_low) < 0) {
3155 std::stringstream oss;
3156 oss << "Read timestamp: " << ucmp->TimestampToString(ts)
3157 << " is smaller than full_history_ts_low: "
3158 << ucmp->TimestampToString(full_history_ts_low) << std::endl;
3159 return Status::InvalidArgument(oss.str());
3160 }
3161 return Status::OK();
3162}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FailIfTsMismatchCf()

Status ROCKSDB_NAMESPACE::DBImpl::FailIfTsMismatchCf ( ColumnFamilyHandle * column_family,
const Slice & ts ) const
inlineprotected

db_impl.h 파일의 3118 번째 라인에서 정의되었습니다.

3119 {
3120 if (!column_family) {
3121 return Status::InvalidArgument("column family handle cannot be null");
3122 }
3123 assert(column_family);
3124 const Comparator* const ucmp = column_family->GetComparator();
3125 assert(ucmp);
3126 if (0 == ucmp->timestamp_size()) {
3127 std::stringstream oss;
3128 oss << "cannot call this method on column family "
3129 << column_family->GetName() << " that does not enable timestamp";
3130 return Status::InvalidArgument(oss.str());
3131 }
3132 const size_t ts_sz = ts.size();
3133 if (ts_sz != ucmp->timestamp_size()) {
3134 std::stringstream oss;
3135 oss << "Timestamp sizes mismatch: expect " << ucmp->timestamp_size() << ", "
3136 << ts_sz << " given";
3137 return Status::InvalidArgument(oss.str());
3138 }
3139 return Status::OK();
3140}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FindMinimumEmptyLevelFitting()

int ROCKSDB_NAMESPACE::DBImpl::FindMinimumEmptyLevelFitting ( ColumnFamilyData * cfd,
const MutableCFOptions & mutable_cf_options,
int level )
private

db_impl.cc 파일의 1526 번째 라인에서 정의되었습니다.

1528 {
1529 mutex_.AssertHeld();
1530 const auto* vstorage = cfd->current()->storage_info();
1531 int minimum_level = level;
1532 for (int i = level - 1; i > 0; --i) {
1533 // stop if level i is not empty
1534 if (vstorage->NumLevelFiles(i) > 0) {
1535 break;
1536 }
1537 // stop if level i is too small (cannot fit the level files)
1538 if (vstorage->MaxBytesForLevel(i) < vstorage->NumLevelBytes(level)) {
1539 break;
1540 }
1541
1542 minimum_level = i;
1543 }
1544 return minimum_level;
1545}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FindObsoleteFiles()

void ROCKSDB_NAMESPACE::DBImpl::FindObsoleteFiles ( JobContext * job_context,
bool force,
bool no_full_scan = false )

db_impl_files.cc 파일의 124 번째 라인에서 정의되었습니다.

125 {
126 mutex_.AssertHeld();
127
128 // if deletion is disabled, do nothing
129 if (disable_delete_obsolete_files_ > 0) {
130 return;
131 }
132
133 bool doing_the_full_scan = false;
134
135 // logic for figuring out if we're doing the full scan
136 if (no_full_scan) {
137 doing_the_full_scan = false;
138 } else if (force ||
140 doing_the_full_scan = true;
141 } else {
142 const uint64_t now_micros = immutable_db_options_.clock->NowMicros();
143 if ((delete_obsolete_files_last_run_ +
145 now_micros) {
146 doing_the_full_scan = true;
148 }
149 }
150
151 // don't delete files that might be currently written to from compaction
152 // threads
153 // Since job_context->min_pending_output is set, until file scan finishes,
154 // mutex_ cannot be released. Otherwise, we might see no min_pending_output
155 // here but later find newer generated unfinalized files while scanning.
156 job_context->min_pending_output = MinObsoleteSstNumberToKeep();
157 job_context->files_to_quarantine = error_handler_.GetFilesToQuarantine();
158 job_context->min_options_file_number = MinOptionsFileNumberToKeep();
159
160 // Get obsolete files. This function will also update the list of
161 // pending files in VersionSet().
162 versions_->GetObsoleteFiles(
163 &job_context->sst_delete_files, &job_context->blob_delete_files,
164 &job_context->manifest_delete_files, job_context->min_pending_output);
165
166 // Mark the elements in job_context->sst_delete_files and
167 // job_context->blob_delete_files as "grabbed for purge" so that other threads
168 // calling FindObsoleteFiles with full_scan=true will not add these files to
169 // candidate list for purge.
170 for (const auto& sst_to_del : job_context->sst_delete_files) {
171 MarkAsGrabbedForPurge(sst_to_del.metadata->fd.GetNumber());
172 }
173
174 for (const auto& blob_file : job_context->blob_delete_files) {
175 MarkAsGrabbedForPurge(blob_file.GetBlobFileNumber());
176 }
177
178 // store the current filenum, lognum, etc
179 job_context->manifest_file_number = versions_->manifest_file_number();
180 job_context->pending_manifest_file_number =
181 versions_->pending_manifest_file_number();
182 job_context->log_number = MinLogNumberToKeep();
183 job_context->prev_log_number = versions_->prev_log_number();
184
185 if (doing_the_full_scan) {
186 versions_->AddLiveFiles(&job_context->sst_live, &job_context->blob_live);
187 InfoLogPrefix info_log_prefix(!immutable_db_options_.db_log_dir.empty(),
188 dbname_);
189 // PurgeObsoleteFiles will dedupe duplicate files.
190 IOOptions io_opts;
191 io_opts.do_not_recurse = true;
192 for (auto& path : CollectAllDBPaths()) {
193 // set of all files in the directory. We'll exclude files that are still
194 // alive in the subsequent processings.
195 std::vector<std::string> files;
196 Status s = immutable_db_options_.fs->GetChildren(
197 path, io_opts, &files, /*IODebugContext*=*/nullptr);
198 s.PermitUncheckedError(); // TODO: What should we do on error?
199 for (const std::string& file : files) {
200 uint64_t number;
202 // 1. If we cannot parse the file name, we skip;
203 // 2. If the file with file_number equals number has already been
204 // grabbed for purge by another compaction job, or it has already been
205 // schedule for purge, we also skip it if we
206 // are doing full scan in order to avoid double deletion of the same
207 // file under race conditions. See
208 // https://github.com/facebook/rocksdb/issues/3573
209 if (!ParseFileName(file, &number, info_log_prefix.prefix, &type) ||
210 !ShouldPurge(number)) {
211 continue;
212 }
213
214 // TODO(icanadi) clean up this mess to avoid having one-off "/"
215 // prefixes
216 job_context->full_scan_candidate_files.emplace_back("/" + file, path);
217 }
218 }
219
220 // Add log files in wal_dir
222 std::vector<std::string> log_files;
223 Status s = immutable_db_options_.fs->GetChildren(
224 immutable_db_options_.wal_dir, io_opts, &log_files,
225 /*IODebugContext*=*/nullptr);
226 s.PermitUncheckedError(); // TODO: What should we do on error?
227 for (const std::string& log_file : log_files) {
228 job_context->full_scan_candidate_files.emplace_back(
230 }
231 }
232
233 // Add info log files in db_log_dir
234 if (!immutable_db_options_.db_log_dir.empty() &&
236 std::vector<std::string> info_log_files;
237 Status s = immutable_db_options_.fs->GetChildren(
238 immutable_db_options_.db_log_dir, io_opts, &info_log_files,
239 /*IODebugContext*=*/nullptr);
240 s.PermitUncheckedError(); // TODO: What should we do on error?
241 for (std::string& log_file : info_log_files) {
242 job_context->full_scan_candidate_files.emplace_back(
244 }
245 }
246 } else {
247 // Instead of filling ob_context->sst_live and job_context->blob_live,
248 // directly remove files that show up in any Version. This is because
249 // candidate files tend to be a small percentage of all files, so it is
250 // usually cheaper to check them against every version, compared to
251 // building a map for all files.
252 versions_->RemoveLiveFiles(job_context->sst_delete_files,
253 job_context->blob_delete_files);
254 }
255
256 // Before potentially releasing mutex and waiting on condvar, increment
257 // pending_purge_obsolete_files_ so that another thread executing
258 // `GetSortedWals` will wait until this thread finishes execution since the
259 // other thread will be waiting for `pending_purge_obsolete_files_`.
260 // pending_purge_obsolete_files_ MUST be decremented if there is nothing to
261 // delete.
263
264 Defer cleanup([job_context, this]() {
265 assert(job_context != nullptr);
266 if (!job_context->HaveSomethingToDelete()) {
267 mutex_.AssertHeld();
269 }
270 });
271
272 // logs_ is empty when called during recovery, in which case there can't yet
273 // be any tracked obsolete logs
275
276 if (alive_log_files_.empty() || logs_.empty()) {
277 mutex_.AssertHeld();
278 // We may reach here if the db is DBImplSecondary
280 return;
281 }
282
283 bool mutex_unlocked = false;
284 if (!alive_log_files_.empty() && !logs_.empty()) {
285 uint64_t min_log_number = job_context->log_number;
286 size_t num_alive_log_files = alive_log_files_.size();
287 // find newly obsoleted log files
288 while (alive_log_files_.begin()->number < min_log_number) {
289 auto& earliest = *alive_log_files_.begin();
291 log_recycle_files_.size() &&
292 earliest.number >= MinLogNumberToRecycle()) {
294 "adding log %" PRIu64 " to recycle list\n",
295 earliest.number);
296 log_recycle_files_.push_back(earliest.number);
297 } else {
298 job_context->log_delete_files.push_back(earliest.number);
299 }
300 if (job_context->size_log_to_delete == 0) {
301 job_context->prev_total_log_size = total_log_size_;
302 job_context->num_alive_log_files = num_alive_log_files;
303 }
304 job_context->size_log_to_delete += earliest.size;
305 total_log_size_ -= earliest.size;
306 alive_log_files_.pop_front();
307
308 // Current log should always stay alive since it can't have
309 // number < MinLogNumber().
310 assert(alive_log_files_.size());
311 }
313 mutex_.Unlock();
314 mutex_unlocked = true;
315 TEST_SYNC_POINT_CALLBACK("FindObsoleteFiles::PostMutexUnlock", nullptr);
317 while (!logs_.empty() && logs_.front().number < min_log_number) {
318 auto& log = logs_.front();
319 if (log.IsSyncing()) {
321 // logs_ could have changed while we were waiting.
322 continue;
323 }
324 // This WAL file is not live, so it's OK if we never sync the rest of it.
325 // If it's already closed, then it's been fully synced. If
326 // !background_close_inactive_wals then we need to Close it before
327 // removing from logs_ but not blocking while holding log_write_mutex_.
329 log.writer->file()) {
330 // We are taking ownership of and pinning the front entry, so we can
331 // expect it to be the same after releasing and re-acquiring the lock
332 log.PrepareForSync();
334 // TODO: maybe check the return value of Close.
335 // TODO: plumb Env::IOActivity, Env::IOPriority
336 auto s = log.writer->file()->Close({});
337 s.PermitUncheckedError();
339 log.writer->PublishIfClosed();
340 assert(&log == &logs_.front());
341 log.FinishSync();
343 }
344 logs_to_free_.push_back(log.ReleaseWriter());
345 logs_.pop_front();
346 }
347 // Current log cannot be obsolete.
348 assert(!logs_.empty());
349 }
350
351 // We're just cleaning up for DB::Write().
352 assert(job_context->logs_to_free.empty());
353 job_context->logs_to_free = logs_to_free_;
354
355 logs_to_free_.clear();
357 if (mutex_unlocked) {
358 mutex_.Lock();
359 }
360 job_context->log_recycle_files.assign(log_recycle_files_.begin(),
361 log_recycle_files_.end());
362}
std::set< std::string > CollectAllDBPaths()
void MarkAsGrabbedForPurge(uint64_t file_number)
bool ShouldPurge(uint64_t file_number) const
autovector< log::Writer * > logs_to_free_
Definition db_impl.h:2768
std::deque< uint64_t > log_recycle_files_
Definition db_impl.h:2644
uint64_t MinObsoleteSstNumberToKeep()
uint64_t MinOptionsFileNumberToKeep()
const autovector< uint64_t > & GetFilesToQuarantine() const
cleanup(version_str, config)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FindStatsByTime()

bool ROCKSDB_NAMESPACE::DBImpl::FindStatsByTime ( uint64_t start_time,
uint64_t end_time,
uint64_t * new_time,
std::map< std::string, uint64_t > * stats_map )

db_impl.cc 파일의 1113 번째 라인에서 정의되었습니다.

1115 {
1116 assert(new_time);
1117 assert(stats_map);
1118 if (!new_time || !stats_map) {
1119 return false;
1120 }
1121 // lock when search for start_time
1122 {
1123 InstrumentedMutexLock l(&stats_history_mutex_);
1124 auto it = stats_history_.lower_bound(start_time);
1125 if (it != stats_history_.end() && it->first < end_time) {
1126 // make a copy for timestamp and stats_map
1127 *new_time = it->first;
1128 *stats_map = it->second;
1129 return true;
1130 } else {
1131 return false;
1132 }
1133 }
1134}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Flush() [1/3]

virtual Status ROCKSDB_NAMESPACE::DB::Flush ( const FlushOptions & options)
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 1655 번째 라인에서 정의되었습니다.

1655 {
1656 return Flush(options, DefaultColumnFamily());
1657 }
Status Flush(const FlushOptions &options, ColumnFamilyHandle *column_family) override

◆ Flush() [2/3]

Status ROCKSDB_NAMESPACE::DBImpl::Flush ( const FlushOptions & options,
ColumnFamilyHandle * column_family )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_compaction_flush.cc 파일의 1961 번째 라인에서 정의되었습니다.

1962 {
1963 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1964 ROCKS_LOG_INFO(immutable_db_options_.info_log, "[%s] Manual flush start.",
1965 cfh->GetName().c_str());
1966 Status s;
1968 s = AtomicFlushMemTables(flush_options, FlushReason::kManualFlush,
1969 {cfh->cfd()});
1970 } else {
1971 s = FlushMemTable(cfh->cfd(), flush_options, FlushReason::kManualFlush);
1972 }
1973
1975 "[%s] Manual flush finished, status: %s\n",
1976 cfh->GetName().c_str(), s.ToString().c_str());
1977 return s;
1978}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Flush() [3/3]

Status ROCKSDB_NAMESPACE::DBImpl::Flush ( const FlushOptions & options,
const std::vector< ColumnFamilyHandle * > & column_families )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_compaction_flush.cc 파일의 1980 번째 라인에서 정의되었습니다.

1981 {
1982 Status s;
1984 for (auto cfh : column_families) {
1985 s = Flush(flush_options, cfh);
1986 if (!s.ok()) {
1987 break;
1988 }
1989 }
1990 } else {
1992 "Manual atomic flush start.\n"
1993 "=====Column families:=====");
1994 for (auto cfh : column_families) {
1995 auto cfhi = static_cast<ColumnFamilyHandleImpl*>(cfh);
1997 cfhi->GetName().c_str());
1998 }
2000 "=====End of column families list=====");
2001 autovector<ColumnFamilyData*> cfds;
2002 std::for_each(column_families.begin(), column_families.end(),
2003 [&cfds](ColumnFamilyHandle* elem) {
2004 auto cfh = static_cast<ColumnFamilyHandleImpl*>(elem);
2005 cfds.emplace_back(cfh->cfd());
2006 });
2007 s = AtomicFlushMemTables(flush_options, FlushReason::kManualFlush, cfds);
2009 "Manual atomic flush finished, status: %s\n"
2010 "=====Column families:=====",
2011 s.ToString().c_str());
2012 for (auto cfh : column_families) {
2013 auto cfhi = static_cast<ColumnFamilyHandleImpl*>(cfh);
2015 cfhi->GetName().c_str());
2016 }
2018 "=====End of column families list=====");
2019 }
2020 return s;
2021}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ FlushAllColumnFamilies()

Status ROCKSDB_NAMESPACE::DBImpl::FlushAllColumnFamilies ( const FlushOptions & flush_options,
FlushReason flush_reason )
protected

db_impl_compaction_flush.cc 파일의 1930 번째 라인에서 정의되었습니다.

1931 {
1932 mutex_.AssertHeld();
1933 Status status;
1935 mutex_.Unlock();
1936 status = AtomicFlushMemTables(flush_options, flush_reason);
1937 if (status.IsColumnFamilyDropped()) {
1938 status = Status::OK();
1939 }
1940 mutex_.Lock();
1941 } else {
1942 for (auto cfd : versions_->GetRefedColumnFamilySet()) {
1943 if (cfd->IsDropped()) {
1944 continue;
1945 }
1946 mutex_.Unlock();
1947 status = FlushMemTable(cfd, flush_options, flush_reason);
1948 TEST_SYNC_POINT("DBImpl::FlushAllColumnFamilies:1");
1949 TEST_SYNC_POINT("DBImpl::FlushAllColumnFamilies:2");
1950 mutex_.Lock();
1951 if (!status.ok() && !status.IsColumnFamilyDropped()) {
1952 break;
1953 } else if (status.IsColumnFamilyDropped()) {
1954 status = Status::OK();
1955 }
1956 }
1957 }
1958 return status;
1959}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushForGetLiveFiles()

Status ROCKSDB_NAMESPACE::DBImpl::FlushForGetLiveFiles ( )
protectedvirtual

ROCKSDB_NAMESPACE::CompactedDBImpl, ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_filesnapshot.cc 파일의 32 번째 라인에서 정의되었습니다.

32 {
33 return DBImpl::FlushAllColumnFamilies(FlushOptions(),
34 FlushReason::kGetLiveFiles);
35}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushInfoLog()

void ROCKSDB_NAMESPACE::DBImpl::FlushInfoLog ( )

db_impl.cc 파일의 1229 번째 라인에서 정의되었습니다.

1229 {
1230 if (shutdown_initiated_) {
1231 return;
1232 }
1233 TEST_SYNC_POINT("DBImpl::FlushInfoLog:StartRunning");
1235}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushMemTable()

Status ROCKSDB_NAMESPACE::DBImpl::FlushMemTable ( ColumnFamilyData * cfd,
const FlushOptions & options,
FlushReason flush_reason,
bool entered_write_thread = false )
private

db_impl_compaction_flush.cc 파일의 2276 번째 라인에서 정의되었습니다.

2279 {
2280 // This method should not be called if atomic_flush is true.
2282 if (!flush_options.wait && write_controller_.IsStopped()) {
2283 std::ostringstream oss;
2284 oss << "Writes have been stopped, thus unable to perform manual flush. "
2285 "Please try again later after writes are resumed";
2286 return Status::TryAgain(oss.str());
2287 }
2288 Status s;
2289 if (!flush_options.allow_write_stall) {
2290 bool flush_needed = true;
2291 s = WaitUntilFlushWouldNotStallWrites(cfd, &flush_needed);
2292 TEST_SYNC_POINT("DBImpl::FlushMemTable:StallWaitDone");
2293 if (!s.ok() || !flush_needed) {
2294 return s;
2295 }
2296 }
2297
2298 const bool needs_to_join_write_thread = !entered_write_thread;
2299 autovector<FlushRequest> flush_reqs;
2300 autovector<uint64_t> memtable_ids_to_wait;
2301 {
2302 WriteContext context;
2303 InstrumentedMutexLock guard_lock(&mutex_);
2304
2305 WriteThread::Writer w;
2306 WriteThread::Writer nonmem_w;
2307 if (needs_to_join_write_thread) {
2308 write_thread_.EnterUnbatched(&w, &mutex_);
2309 if (two_write_queues_) {
2310 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
2311 }
2312 }
2314
2315 if (!cfd->mem()->IsEmpty() || !cached_recoverable_state_empty_.load() ||
2316 IsRecoveryFlush(flush_reason)) {
2317 s = SwitchMemtable(cfd, &context);
2318 }
2319 const uint64_t flush_memtable_id = std::numeric_limits<uint64_t>::max();
2320 if (s.ok()) {
2321 if (cfd->imm()->NumNotFlushed() != 0 || !cfd->mem()->IsEmpty() ||
2323 IsRecoveryFlush(flush_reason)) {
2324 FlushRequest req{flush_reason, {{cfd, flush_memtable_id}}};
2325 flush_reqs.emplace_back(std::move(req));
2326 memtable_ids_to_wait.emplace_back(
2327 cfd->imm()->GetLatestMemTableID(false /* for_atomic_flush */));
2328 }
2330 ColumnFamilyData* cfd_stats =
2331 versions_->GetColumnFamilySet()->GetColumnFamily(
2332 kPersistentStatsColumnFamilyName);
2333 if (cfd_stats != nullptr && cfd_stats != cfd &&
2334 !cfd_stats->mem()->IsEmpty()) {
2335 // only force flush stats CF when it will be the only CF lagging
2336 // behind after the current flush
2337 bool stats_cf_flush_needed = true;
2338 for (auto* loop_cfd : *versions_->GetColumnFamilySet()) {
2339 if (loop_cfd == cfd_stats || loop_cfd == cfd) {
2340 continue;
2341 }
2342 if (loop_cfd->GetLogNumber() <= cfd_stats->GetLogNumber()) {
2343 stats_cf_flush_needed = false;
2344 }
2345 }
2346 if (stats_cf_flush_needed) {
2348 "Force flushing stats CF with manual flush of %s "
2349 "to avoid holding old logs",
2350 cfd->GetName().c_str());
2351 s = SwitchMemtable(cfd_stats, &context);
2352 FlushRequest req{flush_reason, {{cfd_stats, flush_memtable_id}}};
2353 flush_reqs.emplace_back(std::move(req));
2354 memtable_ids_to_wait.emplace_back(
2355 cfd_stats->imm()->GetLatestMemTableID(
2356 false /* for_atomic_flush */));
2357 }
2358 }
2359 }
2360 }
2361
2362 if (s.ok() && !flush_reqs.empty()) {
2363 for (const auto& req : flush_reqs) {
2364 assert(req.cfd_to_max_mem_id_to_persist.size() == 1);
2365 ColumnFamilyData* loop_cfd =
2366 req.cfd_to_max_mem_id_to_persist.begin()->first;
2367 loop_cfd->imm()->FlushRequested();
2368 }
2369 // If the caller wants to wait for this flush to complete, it indicates
2370 // that the caller expects the ColumnFamilyData not to be free'ed by
2371 // other threads which may drop the column family concurrently.
2372 // Therefore, we increase the cfd's ref count.
2373 if (flush_options.wait) {
2374 for (const auto& req : flush_reqs) {
2375 assert(req.cfd_to_max_mem_id_to_persist.size() == 1);
2376 ColumnFamilyData* loop_cfd =
2377 req.cfd_to_max_mem_id_to_persist.begin()->first;
2378 loop_cfd->Ref();
2379 }
2380 }
2381 for (const auto& req : flush_reqs) {
2382 assert(req.cfd_to_max_mem_id_to_persist.size() == 1);
2383 ColumnFamilyData* loop_cfd =
2384 req.cfd_to_max_mem_id_to_persist.begin()->first;
2385 bool already_queued_for_flush = loop_cfd->queued_for_flush();
2386 bool flush_req_enqueued = EnqueuePendingFlush(req);
2387 if (already_queued_for_flush || flush_req_enqueued) {
2388 loop_cfd->SetFlushSkipReschedule();
2389 }
2390 }
2392 }
2393
2394 if (needs_to_join_write_thread) {
2396 if (two_write_queues_) {
2398 }
2399 }
2400 }
2401
2402 NotifyOnManualFlushScheduled({cfd}, flush_reason);
2403 TEST_SYNC_POINT("DBImpl::FlushMemTable:AfterScheduleFlush");
2404 TEST_SYNC_POINT("DBImpl::FlushMemTable:BeforeWaitForBgFlush");
2405 if (s.ok() && flush_options.wait) {
2406 autovector<ColumnFamilyData*> cfds;
2407 autovector<const uint64_t*> flush_memtable_ids;
2408 assert(flush_reqs.size() == memtable_ids_to_wait.size());
2409 for (size_t i = 0; i < flush_reqs.size(); ++i) {
2410 assert(flush_reqs[i].cfd_to_max_mem_id_to_persist.size() == 1);
2411 cfds.push_back(flush_reqs[i].cfd_to_max_mem_id_to_persist.begin()->first);
2412 flush_memtable_ids.push_back(&(memtable_ids_to_wait[i]));
2413 }
2415 cfds, flush_memtable_ids,
2416 flush_reason == FlushReason::kErrorRecovery /* resuming_from_bg_err */,
2417 flush_reason);
2418 InstrumentedMutexLock lock_guard(&mutex_);
2419 for (auto* tmp_cfd : cfds) {
2420 tmp_cfd->UnrefAndTryDelete();
2421 }
2422 }
2423 TEST_SYNC_POINT("DBImpl::FlushMemTable:FlushMemTableFinished");
2424 return s;
2425}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushMemTablesToOutputFiles()

Status ROCKSDB_NAMESPACE::DBImpl::FlushMemTablesToOutputFiles ( const autovector< BGFlushArg > & bg_flush_args,
bool * made_progress,
JobContext * job_context,
LogBuffer * log_buffer,
Env::Priority thread_pri )
private

db_impl_compaction_flush.cc 파일의 391 번째 라인에서 정의되었습니다.

393 {
396 bg_flush_args, made_progress, job_context, log_buffer, thread_pri);
397 }
398 assert(bg_flush_args.size() == 1);
399 std::vector<SequenceNumber> snapshot_seqs;
400 SequenceNumber earliest_write_conflict_snapshot;
401 SnapshotChecker* snapshot_checker;
402 GetSnapshotContext(job_context, &snapshot_seqs,
403 &earliest_write_conflict_snapshot, &snapshot_checker);
404 const auto& bg_flush_arg = bg_flush_args[0];
405 ColumnFamilyData* cfd = bg_flush_arg.cfd_;
406 // intentional infrequent copy for each flush
407 MutableCFOptions mutable_cf_options_copy = *cfd->GetLatestMutableCFOptions();
408 SuperVersionContext* superversion_context =
409 bg_flush_arg.superversion_context_;
410 FlushReason flush_reason = bg_flush_arg.flush_reason_;
411 Status s = FlushMemTableToOutputFile(
412 cfd, mutable_cf_options_copy, made_progress, job_context, flush_reason,
413 superversion_context, snapshot_seqs, earliest_write_conflict_snapshot,
414 snapshot_checker, log_buffer, thread_pri);
415 return s;
416}
Status AtomicFlushMemTablesToOutputFiles(const autovector< BGFlushArg > &bg_flush_args, bool *made_progress, JobContext *job_context, LogBuffer *log_buffer, Env::Priority thread_pri)
Status FlushMemTableToOutputFile(ColumnFamilyData *cfd, const MutableCFOptions &mutable_cf_options, bool *madeProgress, JobContext *job_context, FlushReason flush_reason, SuperVersionContext *superversion_context, std::vector< SequenceNumber > &snapshot_seqs, SequenceNumber earliest_write_conflict_snapshot, SnapshotChecker *snapshot_checker, LogBuffer *log_buffer, Env::Priority thread_pri)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushMemTableToOutputFile()

Status ROCKSDB_NAMESPACE::DBImpl::FlushMemTableToOutputFile ( ColumnFamilyData * cfd,
const MutableCFOptions & mutable_cf_options,
bool * madeProgress,
JobContext * job_context,
FlushReason flush_reason,
SuperVersionContext * superversion_context,
std::vector< SequenceNumber > & snapshot_seqs,
SequenceNumber earliest_write_conflict_snapshot,
SnapshotChecker * snapshot_checker,
LogBuffer * log_buffer,
Env::Priority thread_pri )
private

db_impl_compaction_flush.cc 파일의 143 번째 라인에서 정의되었습니다.

150 {
151 mutex_.AssertHeld();
152 assert(cfd);
153 assert(cfd->imm());
154 assert(cfd->imm()->NumNotFlushed() != 0);
155 assert(cfd->imm()->IsFlushPending());
156 assert(versions_);
157 assert(versions_->GetColumnFamilySet());
158 const ReadOptions read_options(Env::IOActivity::kFlush);
159 const WriteOptions write_options(Env::IOActivity::kFlush);
160 // If there are more than one column families, we need to make sure that
161 // all the log files except the most recent one are synced. Otherwise if
162 // the host crashes after flushing and before WAL is persistent, the
163 // flushed SST may contain data from write batches whose updates to
164 // other (unflushed) column families are missing.
165 //
166 // When 2PC is enabled, non-recent WAL(s) may be needed for crash-recovery,
167 // even when there is only one CF in the DB, for prepared transactions that
168 // had not been committed yet. Make sure we sync them to keep the persisted
169 // WAL state at least as new as the persisted SST state.
170 const bool needs_to_sync_closed_wals =
171 logfile_number_ > 0 &&
172 (versions_->GetColumnFamilySet()->NumberOfColumnFamilies() > 1 ||
173 allow_2pc());
174
175 // If needs_to_sync_closed_wals is true, we need to record the current
176 // maximum memtable ID of this column family so that a later PickMemtables()
177 // call will not pick memtables whose IDs are higher. This is due to the fact
178 // that SyncClosedWals() may release the db mutex, and memtable switch can
179 // happen for this column family in the meantime. The newly created memtables
180 // have their data backed by unsynced WALs, thus they cannot be included in
181 // this flush job.
182 // Another reason why we must record the current maximum memtable ID of this
183 // column family: SyncClosedWals() may release db mutex, thus it's possible
184 // for application to continue to insert into memtables increasing db's
185 // sequence number. The application may take a snapshot, but this snapshot is
186 // not included in `snapshot_seqs` which will be passed to flush job because
187 // `snapshot_seqs` has already been computed before this function starts.
188 // Recording the max memtable ID ensures that the flush job does not flush
189 // a memtable without knowing such snapshot(s).
190 uint64_t max_memtable_id =
191 needs_to_sync_closed_wals
192 ? cfd->imm()->GetLatestMemTableID(false /* for_atomic_flush */)
193 : std::numeric_limits<uint64_t>::max();
194
195 // If needs_to_sync_closed_wals is false, then the flush job will pick ALL
196 // existing memtables of the column family when PickMemTable() is called
197 // later. Although we won't call SyncClosedWals() in this case, we may still
198 // call the callbacks of the listeners, i.e. NotifyOnFlushBegin() which also
199 // releases and re-acquires the db mutex. In the meantime, the application
200 // can still insert into the memtables and increase the db's sequence number.
201 // The application can take a snapshot, hoping that the latest visible state
202 // to this snapshot is preserved. This is hard to guarantee since db mutex
203 // not held. This newly-created snapshot is not included in `snapshot_seqs`
204 // and the flush job is unaware of its presence. Consequently, the flush job
205 // may drop certain keys when generating the L0, causing incorrect data to be
206 // returned for snapshot read using this snapshot.
207 // To address this, we make sure NotifyOnFlushBegin() executes after memtable
208 // picking so that no new snapshot can be taken between the two functions.
209
210 FlushJob flush_job(
211 dbname_, cfd, immutable_db_options_, mutable_cf_options, max_memtable_id,
212 file_options_for_compaction_, versions_.get(), &mutex_, &shutting_down_,
213 snapshot_seqs, earliest_write_conflict_snapshot, snapshot_checker,
214 job_context, flush_reason, log_buffer, directories_.GetDbDir(),
215 GetDataDir(cfd, 0U),
216 GetCompressionFlush(*cfd->ioptions(), mutable_cf_options), stats_,
217 &event_logger_, mutable_cf_options.report_bg_io_stats,
218 true /* sync_output_directory */, true /* write_manifest */, thread_pri,
219 io_tracer_, cfd->GetSuperVersion()->ShareSeqnoToTimeMapping(), db_id_,
220 db_session_id_, cfd->GetFullHistoryTsLow(), &blob_callback_);
221 FileMetaData file_meta;
222
223 Status s;
224 bool need_cancel = false;
225 IOStatus log_io_s = IOStatus::OK();
226 if (needs_to_sync_closed_wals) {
227 // SyncClosedWals() may unlock and re-lock the log_write_mutex multiple
228 // times.
229 VersionEdit synced_wals;
230 bool error_recovery_in_prog = error_handler_.IsRecoveryInProgress();
231 mutex_.Unlock();
232 log_io_s = SyncClosedWals(write_options, job_context, &synced_wals,
233 error_recovery_in_prog);
234 mutex_.Lock();
235 if (log_io_s.ok() && synced_wals.IsWalAddition()) {
236 log_io_s = status_to_io_status(
237 ApplyWALToManifest(read_options, write_options, &synced_wals));
238 TEST_SYNC_POINT_CALLBACK("DBImpl::FlushMemTableToOutputFile:CommitWal:1",
239 nullptr);
240 }
241
242 if (!log_io_s.ok() && !log_io_s.IsShutdownInProgress() &&
243 !log_io_s.IsColumnFamilyDropped()) {
244 error_handler_.SetBGError(log_io_s, BackgroundErrorReason::kFlush);
245 }
246 } else {
247 TEST_SYNC_POINT("DBImpl::SyncClosedWals:Skip");
248 }
249 s = log_io_s;
250
251 // If the log sync failed, we do not need to pick memtable. Otherwise,
252 // num_flush_not_started_ needs to be rollback.
253 TEST_SYNC_POINT("DBImpl::FlushMemTableToOutputFile:BeforePickMemtables");
254 // Exit a flush due to bg error should not set bg error again.
255 bool skip_set_bg_error = false;
256 if (s.ok() && !error_handler_.GetBGError().ok() &&
258 flush_reason != FlushReason::kErrorRecovery &&
259 flush_reason != FlushReason::kErrorRecoveryRetryFlush) {
260 // Error recovery in progress, should not pick memtable which excludes
261 // them from being picked up by recovery flush.
262 // This ensures that when bg error is set, no new flush can pick
263 // memtables.
264 skip_set_bg_error = true;
266 assert(!s.ok());
267 ROCKS_LOG_BUFFER(log_buffer,
268 "[JOB %d] Skip flush due to background error %s",
269 job_context->job_id, s.ToString().c_str());
270 }
271
272 if (s.ok()) {
273 flush_job.PickMemTable();
274 need_cancel = true;
275 }
277 "DBImpl::FlushMemTableToOutputFile:AfterPickMemtables", &flush_job);
278
279 // may temporarily unlock and lock the mutex.
280 NotifyOnFlushBegin(cfd, &file_meta, mutable_cf_options, job_context->job_id,
281 flush_reason);
282
283 bool switched_to_mempurge = false;
284 // Within flush_job.Run, rocksdb may call event listener to notify
285 // file creation and deletion.
286 //
287 // Note that flush_job.Run will unlock and lock the db_mutex,
288 // and EventListener callback will be called when the db_mutex
289 // is unlocked by the current thread.
290 if (s.ok()) {
291 s = flush_job.Run(&logs_with_prep_tracker_, &file_meta,
292 &switched_to_mempurge, &skip_set_bg_error,
293 &error_handler_);
294 need_cancel = false;
295 }
296
297 if (!s.ok() && need_cancel) {
298 flush_job.Cancel();
299 }
300
301 if (s.ok()) {
302 InstallSuperVersionAndScheduleWork(cfd, superversion_context,
303 mutable_cf_options);
304 if (made_progress) {
305 *made_progress = true;
306 }
307
308 const std::string& column_family_name = cfd->GetName();
309
310 Version* const current = cfd->current();
311 assert(current);
312
313 const VersionStorageInfo* const storage_info = current->storage_info();
314 assert(storage_info);
315
316 VersionStorageInfo::LevelSummaryStorage tmp;
317 ROCKS_LOG_BUFFER(log_buffer, "[%s] Level summary: %s\n",
318 column_family_name.c_str(),
319 storage_info->LevelSummary(&tmp));
320
321 const auto& blob_files = storage_info->GetBlobFiles();
322 if (!blob_files.empty()) {
323 assert(blob_files.front());
324 assert(blob_files.back());
325
327 log_buffer,
328 "[%s] Blob file summary: head=%" PRIu64 ", tail=%" PRIu64 "\n",
329 column_family_name.c_str(), blob_files.front()->GetBlobFileNumber(),
330 blob_files.back()->GetBlobFileNumber());
331 }
332 }
333
334 if (!s.ok() && !s.IsShutdownInProgress() && !s.IsColumnFamilyDropped() &&
335 !skip_set_bg_error) {
336 if (log_io_s.ok()) {
337 // Error while writing to MANIFEST.
338 // In fact, versions_->io_status() can also be the result of renaming
339 // CURRENT file. With current code, it's just difficult to tell. So just
340 // be pessimistic and try write to a new MANIFEST.
341 // TODO: distinguish between MANIFEST write and CURRENT renaming
342 if (!versions_->io_status().ok()) {
343 // If WAL sync is successful (either WAL size is 0 or there is no IO
344 // error), all the Manifest write will be map to soft error.
345 // TODO: kManifestWriteNoWAL and kFlushNoWAL are misleading. Refactor is
346 // needed.
348 BackgroundErrorReason::kManifestWriteNoWAL);
349 } else {
350 // If WAL sync is successful (either WAL size is 0 or there is no IO
351 // error), all the other SST file write errors will be set as
352 // kFlushNoWAL.
353 error_handler_.SetBGError(s, BackgroundErrorReason::kFlushNoWAL);
354 }
355 } else {
356 assert(s == log_io_s);
357 Status new_bg_error = s;
358 error_handler_.SetBGError(new_bg_error, BackgroundErrorReason::kFlush);
359 }
360 }
361 // If flush ran smoothly and no mempurge happened
362 // install new SST file path.
363 if (s.ok() && (!switched_to_mempurge)) {
364 // may temporarily unlock and lock the mutex.
365 NotifyOnFlushCompleted(cfd, mutable_cf_options,
366 flush_job.GetCommittedFlushJobsInfo());
367 auto sfm = static_cast<SstFileManagerImpl*>(
369 if (sfm) {
370 // Notify sst_file_manager that a new file was added
371 std::string file_path = MakeTableFileName(
372 cfd->ioptions()->cf_paths[0].path, file_meta.fd.GetNumber());
373 // TODO (PR7798). We should only add the file to the FileManager if it
374 // exists. Otherwise, some tests may fail. Ignore the error in the
375 // interim.
376 sfm->OnAddFile(file_path).PermitUncheckedError();
377 if (sfm->IsMaxAllowedSpaceReached()) {
378 Status new_bg_error =
379 Status::SpaceLimit("Max allowed space was reached");
381 "DBImpl::FlushMemTableToOutputFile:MaxAllowedSpaceReached",
382 &new_bg_error);
383 error_handler_.SetBGError(new_bg_error, BackgroundErrorReason::kFlush);
384 }
385 }
386 }
387 TEST_SYNC_POINT("DBImpl::FlushMemTableToOutputFile:Finish");
388 return s;
389}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushWAL() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::FlushWAL ( bool sync)
inlineoverridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.h 파일의 460 번째 라인에서 정의되었습니다.

460 {
461 // TODO: plumb Env::IOActivity, Env::IOPriority
462 return FlushWAL(WriteOptions(), sync);
463 }
Status FlushWAL(bool sync) override
Definition db_impl.h:460
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ FlushWAL() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::FlushWAL ( const WriteOptions & write_options,
bool sync )
virtual

db_impl.cc 파일의 1547 번째 라인에서 정의되었습니다.

1547 {
1548 if (manual_wal_flush_) {
1549 IOStatus io_s;
1550 {
1551 // We need to lock log_write_mutex_ since logs_ might change concurrently
1552 InstrumentedMutexLock wl(&log_write_mutex_);
1553 log::Writer* cur_log_writer = logs_.back().writer;
1554 io_s = cur_log_writer->WriteBuffer(write_options);
1555 }
1556 if (!io_s.ok()) {
1557 ROCKS_LOG_ERROR(immutable_db_options_.info_log, "WAL flush error %s",
1558 io_s.ToString().c_str());
1559 // In case there is a fs error we should set it globally to prevent the
1560 // future writes
1561 WALIOStatusCheck(io_s);
1562 // whether sync or not, we should abort the rest of function upon error
1563 return static_cast<Status>(io_s);
1564 }
1565 if (!sync) {
1566 ROCKS_LOG_DEBUG(immutable_db_options_.info_log, "FlushWAL sync=false");
1567 return static_cast<Status>(io_s);
1568 }
1569 }
1570 if (!sync) {
1571 return Status::OK();
1572 }
1573 // sync = true
1574 ROCKS_LOG_DEBUG(immutable_db_options_.info_log, "FlushWAL sync=true");
1575 return SyncWAL();
1576}
Status SyncWAL() override
Definition db_impl.cc:1597
void WALIOStatusCheck(const IOStatus &status)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GenerateDbSessionId()

std::string ROCKSDB_NAMESPACE::DBImpl::GenerateDbSessionId ( Env * env)
static

db_impl.cc 파일의 5261 번째 라인에서 정의되었습니다.

5261 {
5262 // See SemiStructuredUniqueIdGen for its desirable properties.
5263 auto gen = DbSessionIdGen();
5264
5265 uint64_t lo, hi;
5266 gen->GenerateNext(&hi, &lo);
5267 if (lo == 0) {
5268 // Avoid emitting session ID with lo==0, so that SST unique
5269 // IDs can be more easily ensured non-zero
5270 gen->GenerateNext(&hi, &lo);
5271 assert(lo != 0);
5272 }
5273 return EncodeSessionId(hi, lo);
5274}
std::string EncodeSessionId(uint64_t upper, uint64_t lower)
Definition unique_id.cc:15
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GenerateFlushRequest()

void ROCKSDB_NAMESPACE::DBImpl::GenerateFlushRequest ( const autovector< ColumnFamilyData * > & cfds,
FlushReason flush_reason,
FlushRequest * req )
private

db_impl_compaction_flush.cc 파일의 2243 번째 라인에서 정의되었습니다.

2244 {
2245 assert(req != nullptr);
2246 req->flush_reason = flush_reason;
2247 req->cfd_to_max_mem_id_to_persist.reserve(cfds.size());
2248 for (const auto cfd : cfds) {
2249 if (nullptr == cfd) {
2250 // cfd may be null, see DBImpl::ScheduleFlushes
2251 continue;
2252 }
2253 uint64_t max_memtable_id = cfd->imm()->GetLatestMemTableID(
2254 immutable_db_options_.atomic_flush /* for_atomic_flush */);
2255 req->cfd_to_max_mem_id_to_persist.emplace(cfd, max_memtable_id);
2256 }
2257}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Get() [1/6]

Status ROCKSDB_NAMESPACE::DBImpl::Get ( const ReadOptions & _read_options,
ColumnFamilyHandle * column_family,
const Slice & key,
PinnableSlice * value,
std::string * timestamp )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 2167 번째 라인에서 정의되었습니다.

2169 {
2170 assert(value != nullptr);
2171 value->Reset();
2172
2173 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
2174 _read_options.io_activity != Env::IOActivity::kGet) {
2175 return Status::InvalidArgument(
2176 "Can only call Get with `ReadOptions::io_activity` is "
2177 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kGet`");
2178 }
2179
2180 ReadOptions read_options(_read_options);
2181 if (read_options.io_activity == Env::IOActivity::kUnknown) {
2182 read_options.io_activity = Env::IOActivity::kGet;
2183 }
2184
2185 Status s = GetImpl(read_options, column_family, key, value, timestamp);
2186 return s;
2187}
Status GetImpl(const ReadOptions &read_options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *value)
Definition db_impl.cc:2160
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Get() [2/6]

virtual Status ROCKSDB_NAMESPACE::DB::Get ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
PinnableSlice * value )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 633 번째 라인에서 정의되었습니다.

635 {
636 return Get(options, column_family, key, value, nullptr);
637 }
Status Get(const ReadOptions &_read_options, ColumnFamilyHandle *column_family, const Slice &key, PinnableSlice *value, std::string *timestamp) override
Definition db_impl.cc:2167

◆ Get() [3/6]

virtual Status ROCKSDB_NAMESPACE::DB::Get ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
std::string * value )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 641 번째 라인에서 정의되었습니다.

643 {
644 assert(value != nullptr);
645 PinnableSlice pinnable_val(value);
646 assert(!pinnable_val.IsPinned());
647 auto s = Get(options, column_family, key, &pinnable_val);
648 if (s.ok() && pinnable_val.IsPinned()) {
649 value->assign(pinnable_val.data(), pinnable_val.size());
650 } // else value is already assigned
651 return s;
652 }

◆ Get() [4/6]

virtual Status ROCKSDB_NAMESPACE::DB::Get ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
std::string * value,
std::string * timestamp )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 618 번째 라인에서 정의되었습니다.

620 {
621 assert(value != nullptr);
622 PinnableSlice pinnable_val(value);
623 assert(!pinnable_val.IsPinned());
624 auto s = Get(options, column_family, key, &pinnable_val, timestamp);
625 if (s.ok() && pinnable_val.IsPinned()) {
626 value->assign(pinnable_val.data(), pinnable_val.size());
627 } // else value is already assigned
628 return s;
629 }

◆ Get() [5/6]

virtual Status ROCKSDB_NAMESPACE::DB::Get ( const ReadOptions & options,
const Slice & key,
std::string * value )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 657 번째 라인에서 정의되었습니다.

658 {
659 return Get(options, DefaultColumnFamily(), key, value);
660 }

◆ Get() [6/6]

virtual Status ROCKSDB_NAMESPACE::DB::Get ( const ReadOptions & options,
const Slice & key,
std::string * value,
std::string * timestamp )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 665 번째 라인에서 정의되었습니다.

666 {
667 return Get(options, DefaultColumnFamily(), key, value, timestamp);
668 }

◆ GetAggregatedIntProperty()

bool ROCKSDB_NAMESPACE::DBImpl::GetAggregatedIntProperty ( const Slice & property,
uint64_t * aggregated_value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4632 번째 라인에서 정의되었습니다.

4633 {
4634 const DBPropertyInfo* property_info = GetPropertyInfo(property);
4635 if (property_info == nullptr || property_info->handle_int == nullptr) {
4636 return false;
4637 }
4638 auto aggregator = CreateIntPropertyAggregator(property);
4639 if (aggregator == nullptr) {
4640 return false;
4641 }
4642
4643 bool ret = true;
4644 {
4645 // Needs mutex to protect the list of column families.
4646 InstrumentedMutexLock l(&mutex_);
4647 uint64_t value;
4648 for (auto* cfd : versions_->GetRefedColumnFamilySet()) {
4649 if (!cfd->initialized()) {
4650 continue;
4651 }
4652 ret = GetIntPropertyInternal(cfd, *property_info, true, &value);
4653 // GetIntPropertyInternal may release db mutex and re-acquire it.
4654 mutex_.AssertHeld();
4655 if (ret) {
4656 aggregator->Add(cfd, value);
4657 } else {
4658 ret = false;
4659 break;
4660 }
4661 }
4662 }
4663 *aggregated_value = aggregator->Aggregate();
4664 return ret;
4665}
bool GetIntPropertyInternal(ColumnFamilyData *cfd, const DBPropertyInfo &property_info, bool is_locked, uint64_t *value)
Definition db_impl.cc:4581
std::unique_ptr< IntPropertyAggregator > CreateIntPropertyAggregator(const Slice &property)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetAllColumnFamilyMetaData()

void ROCKSDB_NAMESPACE::DBImpl::GetAllColumnFamilyMetaData ( std::vector< ColumnFamilyMetaData > * metadata)
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 5134 번째 라인에서 정의되었습니다.

5135 {
5136 InstrumentedMutexLock l(&mutex_);
5137 for (auto cfd : *(versions_->GetColumnFamilySet())) {
5138 {
5139 metadata->emplace_back();
5140 cfd->current()->GetColumnFamilyMetaData(&metadata->back());
5141 }
5142 }
5143}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetAndRefSuperVersion() [1/2]

SuperVersion * ROCKSDB_NAMESPACE::DBImpl::GetAndRefSuperVersion ( ColumnFamilyData * cfd)

db_impl.cc 파일의 4667 번째 라인에서 정의되었습니다.

4667 {
4668 // TODO(ljin): consider using GetReferencedSuperVersion() directly
4669 return cfd->GetThreadLocalSuperVersion(this);
4670}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetAndRefSuperVersion() [2/2]

SuperVersion * ROCKSDB_NAMESPACE::DBImpl::GetAndRefSuperVersion ( uint32_t column_family_id)

db_impl.cc 파일의 4674 번째 라인에서 정의되었습니다.

4674 {
4675 auto column_family_set = versions_->GetColumnFamilySet();
4676 auto cfd = column_family_set->GetColumnFamily(column_family_id);
4677 if (!cfd) {
4678 return nullptr;
4679 }
4680
4681 return GetAndRefSuperVersion(cfd);
4682}
SuperVersion * GetAndRefSuperVersion(ColumnFamilyData *cfd)
Definition db_impl.cc:4667
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetApproximateMemTableStats() [1/2]

void ROCKSDB_NAMESPACE::DBImpl::GetApproximateMemTableStats ( ColumnFamilyHandle * column_family,
const Range & range,
uint64_t *const count,
uint64_t *const size )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4750 번째 라인에서 정의되었습니다.

4753 {
4754 ColumnFamilyHandleImpl* cfh =
4755 static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
4756 ColumnFamilyData* cfd = cfh->cfd();
4758
4759 const Comparator* const ucmp = column_family->GetComparator();
4760 assert(ucmp);
4761 size_t ts_sz = ucmp->timestamp_size();
4762
4763 // Add timestamp if needed
4764 std::string start_with_ts, limit_with_ts;
4765 auto [start, limit] = MaybeAddTimestampsToRange(
4766 &range.start, &range.limit, ts_sz, &start_with_ts, &limit_with_ts);
4767 assert(start.has_value());
4768 assert(limit.has_value());
4769 // Convert user_key into a corresponding internal key.
4770 InternalKey k1(start.value(), kMaxSequenceNumber, kValueTypeForSeek);
4771 InternalKey k2(limit.value(), kMaxSequenceNumber, kValueTypeForSeek);
4772 ReadOnlyMemTable::MemTableStats memStats =
4773 sv->mem->ApproximateStats(k1.Encode(), k2.Encode());
4774 ReadOnlyMemTable::MemTableStats immStats =
4775 sv->imm->ApproximateStats(k1.Encode(), k2.Encode());
4776 *count = memStats.count + immStats.count;
4777 *size = memStats.size + immStats.size;
4778
4780}
void ReturnAndCleanupSuperVersion(ColumnFamilyData *cfd, SuperVersion *sv)
Definition db_impl.cc:4704
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetApproximateMemTableStats() [2/2]

virtual void ROCKSDB_NAMESPACE::DB::GetApproximateMemTableStats ( const Range & range,
uint64_t *const count,
uint64_t *const size )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1462 번째 라인에서 정의되었습니다.

1464 {
1465 GetApproximateMemTableStats(DefaultColumnFamily(), range, count, size);
1466 }
void GetApproximateMemTableStats(ColumnFamilyHandle *column_family, const Range &range, uint64_t *const count, uint64_t *const size) override
Definition db_impl.cc:4750

◆ GetApproximateSizes() [1/3]

Status ROCKSDB_NAMESPACE::DB::GetApproximateSizes ( ColumnFamilyHandle * column_family,
const Range * ranges,
int n,
uint64_t * sizes,
SizeApproximationFlags include_flags = SizeApproximationFlags::INCLUDE_FILES )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1442 번째 라인에서 정의되었습니다.

2143 {
2144 SizeApproximationOptions options;
2145 options.include_memtables =
2146 ((include_flags & SizeApproximationFlags::INCLUDE_MEMTABLES) !=
2147 SizeApproximationFlags::NONE);
2148 options.include_files =
2149 ((include_flags & SizeApproximationFlags::INCLUDE_FILES) !=
2150 SizeApproximationFlags::NONE);
2151 return GetApproximateSizes(options, column_family, ranges, n, sizes);
2152}
Status GetApproximateSizes(const SizeApproximationOptions &options, ColumnFamilyHandle *column_family, const Range *range, int n, uint64_t *sizes) override
Definition db_impl.cc:4782
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetApproximateSizes() [2/3]

virtual Status ROCKSDB_NAMESPACE::DB::GetApproximateSizes ( const Range * ranges,
int n,
uint64_t * sizes,
SizeApproximationFlags include_flags = SizeApproximationFlags::INCLUDE_FILES )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1448 번째 라인에서 정의되었습니다.

1451 {
1452 return GetApproximateSizes(DefaultColumnFamily(), ranges, n, sizes,
1453 include_flags);
1454 }

◆ GetApproximateSizes() [3/3]

Status ROCKSDB_NAMESPACE::DBImpl::GetApproximateSizes ( const SizeApproximationOptions & options,
ColumnFamilyHandle * column_family,
const Range * range,
int n,
uint64_t * sizes )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4782 번째 라인에서 정의되었습니다.

4784 {
4785 if (!options.include_memtables && !options.include_files) {
4786 return Status::InvalidArgument("Invalid options");
4787 }
4788
4789 const Comparator* const ucmp = column_family->GetComparator();
4790 assert(ucmp);
4791 size_t ts_sz = ucmp->timestamp_size();
4792
4793 Version* v;
4794 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
4795 auto cfd = cfh->cfd();
4797 v = sv->current;
4798
4799 // TODO: plumb Env::IOActivity, Env::IOPriority
4800 const ReadOptions read_options;
4801 for (int i = 0; i < n; i++) {
4802 // Add timestamp if needed
4803 std::string start_with_ts, limit_with_ts;
4804 auto [start, limit] =
4805 MaybeAddTimestampsToRange(&range[i].start, &range[i].limit, ts_sz,
4806 &start_with_ts, &limit_with_ts);
4807 assert(start.has_value());
4808 assert(limit.has_value());
4809 // Convert user_key into a corresponding internal key.
4810 InternalKey k1(start.value(), kMaxSequenceNumber, kValueTypeForSeek);
4811 InternalKey k2(limit.value(), kMaxSequenceNumber, kValueTypeForSeek);
4812 sizes[i] = 0;
4813 if (options.include_files) {
4814 sizes[i] += versions_->ApproximateSize(
4815 options, read_options, v, k1.Encode(), k2.Encode(),
4816 /*start_level=*/0,
4817 /*end_level=*/-1, TableReaderCaller::kUserApproximateSize);
4818 }
4819 if (options.include_memtables) {
4820 sizes[i] += sv->mem->ApproximateStats(k1.Encode(), k2.Encode()).size;
4821 sizes[i] += sv->imm->ApproximateStats(k1.Encode(), k2.Encode()).size;
4822 }
4823 }
4824
4826 return Status::OK();
4827}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetBGJobLimits() [1/2]

DBImpl::BGJobLimits ROCKSDB_NAMESPACE::DBImpl::GetBGJobLimits ( ) const

db_impl_compaction_flush.cc 파일의 2933 번째 라인에서 정의되었습니다.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetBGJobLimits() [2/2]

DBImpl::BGJobLimits ROCKSDB_NAMESPACE::DBImpl::GetBGJobLimits ( int max_background_flushes,
int max_background_compactions,
int max_background_jobs,
bool parallelize_compactions )
static

db_impl_compaction_flush.cc 파일의 2941 번째 라인에서 정의되었습니다.

2944 {
2945 BGJobLimits res;
2946 if (max_background_flushes == -1 && max_background_compactions == -1) {
2947 // for our first stab implementing max_background_jobs, simply allocate a
2948 // quarter of the threads to flushes.
2949 res.max_flushes = std::max(1, max_background_jobs / 4);
2950 res.max_compactions = std::max(1, max_background_jobs - res.max_flushes);
2951 } else {
2952 // compatibility code in case users haven't migrated to max_background_jobs,
2953 // which automatically computes flush/compaction limits
2954 res.max_flushes = std::max(1, max_background_flushes);
2955 res.max_compactions = std::max(1, max_background_compactions);
2956 }
2957 if (!parallelize_compactions) {
2958 // throttle background compactions until we deem necessary
2959 res.max_compactions = 1;
2960 }
2961 return res;
2962}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetColumnFamilyHandle()

ColumnFamilyHandle * ROCKSDB_NAMESPACE::DBImpl::GetColumnFamilyHandle ( uint32_t column_family_id)

db_impl.cc 파일의 4725 번째 라인에서 정의되었습니다.

4725 {
4726 ColumnFamilyMemTables* cf_memtables = column_family_memtables_.get();
4727
4728 if (!cf_memtables->Seek(column_family_id)) {
4729 return nullptr;
4730 }
4731
4732 return cf_memtables->GetColumnFamilyHandle();
4733}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetColumnFamilyHandleUnlocked()

std::unique_ptr< ColumnFamilyHandle > ROCKSDB_NAMESPACE::DBImpl::GetColumnFamilyHandleUnlocked ( uint32_t column_family_id)

db_impl.cc 파일의 4736 번째 라인에서 정의되었습니다.

4737 {
4738 InstrumentedMutexLock l(&mutex_);
4739
4740 auto* cfd =
4741 versions_->GetColumnFamilySet()->GetColumnFamily(column_family_id);
4742 if (cfd == nullptr) {
4743 return nullptr;
4744 }
4745
4746 return std::unique_ptr<ColumnFamilyHandleImpl>(
4747 new ColumnFamilyHandleImpl(cfd, this, &mutex_));
4748}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetColumnFamilyMetaData()

void ROCKSDB_NAMESPACE::DBImpl::GetColumnFamilyMetaData ( ColumnFamilyHandle * column_family,
ColumnFamilyMetaData * metadata )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 5112 번째 라인에서 정의되었습니다.

5113 {
5114 assert(column_family);
5115 auto* cfd =
5116 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
5117 auto* sv = GetAndRefSuperVersion(cfd);
5118 {
5119 // Without mutex, Version::GetColumnFamilyMetaData will have data race
5120 // with Compaction::MarkFilesBeingCompacted. One solution is to use mutex,
5121 // but this may cause regression. An alternative is to make
5122 // FileMetaData::being_compacted atomic, but it will make FileMetaData
5123 // non-copy-able. Another option is to separate these variables from
5124 // original FileMetaData struct, and this requires re-organization of data
5125 // structures. For now, we take the easy approach. If
5126 // DB::GetColumnFamilyMetaData is not called frequently, the regression
5127 // should not be big. We still need to keep an eye on it.
5128 InstrumentedMutexLock l(&mutex_);
5129 sv->current->GetColumnFamilyMetaData(cf_meta);
5130 }
5132}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetCreationTimeOfOldestFile()

Status ROCKSDB_NAMESPACE::DBImpl::GetCreationTimeOfOldestFile ( uint64_t * creation_time)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 6776 번째 라인에서 정의되었습니다.

6776 {
6778 uint64_t oldest_time = std::numeric_limits<uint64_t>::max();
6779 for (auto cfd : *versions_->GetColumnFamilySet()) {
6780 if (!cfd->IsDropped()) {
6781 uint64_t ctime;
6782 {
6784 Version* version = sv->current;
6785 version->GetCreationTimeOfOldestFile(&ctime);
6787 }
6788
6789 if (ctime < oldest_time) {
6790 oldest_time = ctime;
6791 }
6792 if (oldest_time == 0) {
6793 break;
6794 }
6795 }
6796 }
6797 *creation_time = oldest_time;
6798 return Status::OK();
6799 } else {
6800 return Status::NotSupported("This API only works if max_open_files = -1");
6801 }
6802}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetCurrentWalFile()

Status ROCKSDB_NAMESPACE::DBImpl::GetCurrentWalFile ( std::unique_ptr< WalFile > * current_log_file)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_filesnapshot.cc 파일의 189 번째 라인에서 정의되었습니다.

189 {
190 uint64_t current_logfile_number;
191 {
192 InstrumentedMutexLock l(&mutex_);
193 current_logfile_number = logfile_number_;
194 }
195
196 return wal_manager_.GetLiveWalFile(current_logfile_number, current_log_file);
197}
Status GetLiveWalFile(uint64_t number, std::unique_ptr< WalFile > *log_file)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetDataDir()

FSDirectory * ROCKSDB_NAMESPACE::DBImpl::GetDataDir ( ColumnFamilyData * cfd,
size_t path_id ) const
private

db_impl.cc 파일의 1263 번째 라인에서 정의되었습니다.

1263 {
1264 assert(cfd);
1265 FSDirectory* ret_dir = cfd->GetDataDir(path_id);
1266 if (ret_dir == nullptr) {
1267 return directories_.GetDataDir(path_id);
1268 }
1269 return ret_dir;
1270}
FSDirectory * GetDataDir(size_t path_id) const
Definition db_impl.h:97
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetDbIdentity()

Status ROCKSDB_NAMESPACE::DBImpl::GetDbIdentity ( std::string & identity) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 5224 번째 라인에서 정의되었습니다.

5224 {
5225 identity.assign(db_id_);
5226 return Status::OK();
5227}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetDbIdentityFromIdentityFile()

Status ROCKSDB_NAMESPACE::DBImpl::GetDbIdentityFromIdentityFile ( const IOOptions & opts,
std::string * identity ) const
virtual

db_impl.cc 파일의 5229 번째 라인에서 정의되었습니다.

5230 {
5231 std::string idfilename = IdentityFileName(dbname_);
5232 const FileOptions soptions;
5233
5234 Status s = ReadFileToString(fs_.get(), idfilename, opts, identity);
5235 if (!s.ok()) {
5236 return s;
5237 }
5238
5239 // If last character is '\n' remove it from identity. (Old implementations
5240 // of Env::GenerateUniqueId() would include a trailing '\n'.)
5241 if (identity->size() > 0 && identity->back() == '\n') {
5242 identity->pop_back();
5243 }
5244 return s;
5245}
Status ReadFileToString(Env *env, const std::string &fname, std::string *data)
Definition env.cc:1075
std::string IdentityFileName(const std::string &dbname)
Definition filename.cc:252
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetDBOptions()

DBOptions ROCKSDB_NAMESPACE::DBImpl::GetDBOptions ( ) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4502 번째 라인에서 정의되었습니다.

4502 {
4503 InstrumentedMutexLock l(&mutex_);
4504 return BuildDBOptions(immutable_db_options_, mutable_db_options_);
4505}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetDbSessionId()

Status ROCKSDB_NAMESPACE::DBImpl::GetDbSessionId ( std::string & session_id) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 5247 번째 라인에서 정의되었습니다.

5247 {
5248 session_id.assign(db_session_id_);
5249 return Status::OK();
5250}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetEarliestMemTableSequenceNumber()

SequenceNumber ROCKSDB_NAMESPACE::DBImpl::GetEarliestMemTableSequenceNumber ( SuperVersion * sv,
bool include_history )

db_impl.cc 파일의 5722 번째 라인에서 정의되었습니다.

5723 {
5724 // Find the earliest sequence number that we know we can rely on reading
5725 // from the memtable without needing to check sst files.
5726 SequenceNumber earliest_seq =
5727 sv->imm->GetEarliestSequenceNumber(include_history);
5728 if (earliest_seq == kMaxSequenceNumber) {
5729 earliest_seq = sv->mem->GetEarliestSequenceNumber();
5730 }
5731 assert(sv->mem->GetEarliestSequenceNumber() >= earliest_seq);
5732
5733 return earliest_seq;
5734}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetEntity() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::GetEntity ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
PinnableWideColumns * columns )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 2201 번째 라인에서 정의되었습니다.

2203 {
2204 if (!column_family) {
2205 return Status::InvalidArgument(
2206 "Cannot call GetEntity without a column family handle");
2207 }
2208 if (!columns) {
2209 return Status::InvalidArgument(
2210 "Cannot call GetEntity without a PinnableWideColumns object");
2211 }
2212 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
2213 _read_options.io_activity != Env::IOActivity::kGetEntity) {
2214 return Status::InvalidArgument(
2215 "Can only call GetEntity with `ReadOptions::io_activity` set to "
2216 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kGetEntity`");
2217 }
2218 ReadOptions read_options(_read_options);
2219 if (read_options.io_activity == Env::IOActivity::kUnknown) {
2220 read_options.io_activity = Env::IOActivity::kGetEntity;
2221 }
2222 columns->Reset();
2223
2224 GetImplOptions get_impl_options;
2225 get_impl_options.column_family = column_family;
2226 get_impl_options.columns = columns;
2227
2228 return GetImpl(read_options, key, get_impl_options);
2229}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetEntity() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::GetEntity ( const ReadOptions & options,
const Slice & key,
PinnableAttributeGroups * result )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 2231 번째 라인에서 정의되었습니다.

2232 {
2233 if (!result) {
2234 return Status::InvalidArgument(
2235 "Cannot call GetEntity without PinnableAttributeGroups object");
2236 }
2237 Status s;
2238 const size_t num_column_families = result->size();
2239 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
2240 _read_options.io_activity != Env::IOActivity::kGetEntity) {
2241 s = Status::InvalidArgument(
2242 "Can only call GetEntity with `ReadOptions::io_activity` set to "
2243 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kGetEntity`");
2244 for (size_t i = 0; i < num_column_families; ++i) {
2245 (*result)[i].SetStatus(s);
2246 }
2247 return s;
2248 }
2249 // return early if no CF was passed in
2250 if (num_column_families == 0) {
2251 return s;
2252 }
2253 ReadOptions read_options(_read_options);
2254 if (read_options.io_activity == Env::IOActivity::kUnknown) {
2255 read_options.io_activity = Env::IOActivity::kGetEntity;
2256 }
2257 std::vector<Slice> keys;
2258 std::vector<ColumnFamilyHandle*> column_families;
2259 for (size_t i = 0; i < num_column_families; ++i) {
2260 // If any of the CFH is null, break early since the entire query will fail
2261 if (!(*result)[i].column_family()) {
2262 s = Status::InvalidArgument(
2263 "DB failed to query because one or more group(s) have null column "
2264 "family handle");
2265 (*result)[i].SetStatus(
2266 Status::InvalidArgument("Column family handle cannot be null"));
2267 break;
2268 }
2269 // Adding the same key slice for different CFs
2270 keys.emplace_back(key);
2271 column_families.emplace_back((*result)[i].column_family());
2272 }
2273 if (!s.ok()) {
2274 for (size_t i = 0; i < num_column_families; ++i) {
2275 if ((*result)[i].status().ok()) {
2276 (*result)[i].SetStatus(
2277 Status::Incomplete("DB not queried due to invalid argument(s) in "
2278 "one or more of the attribute groups"));
2279 }
2280 }
2281 return s;
2282 }
2283 std::vector<PinnableWideColumns> columns(num_column_families);
2284 std::vector<Status> statuses(num_column_families);
2286 read_options, num_column_families, column_families.data(), keys.data(),
2287 /* values */ nullptr, columns.data(),
2288 /* timestamps */ nullptr, statuses.data(), /* sorted_input */ false);
2289 // Set results
2290 for (size_t i = 0; i < num_column_families; ++i) {
2291 (*result)[i].Reset();
2292 (*result)[i].SetStatus(statuses[i]);
2293 (*result)[i].SetColumns(std::move(columns[i]));
2294 }
2295 return s;
2296}
void MultiGetCommon(const ReadOptions &options, ColumnFamilyHandle *column_family, const size_t num_keys, const Slice *keys, PinnableSlice *values, PinnableWideColumns *columns, std::string *timestamps, Status *statuses, bool sorted_input)
Definition db_impl.cc:3045
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetEnv()

Env * ROCKSDB_NAMESPACE::DBImpl::GetEnv ( ) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4468 번째 라인에서 정의되었습니다.

4468{ return env_; }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetFileSystem()

FileSystem * ROCKSDB_NAMESPACE::DBImpl::GetFileSystem ( ) const
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 4475 번째 라인에서 정의되었습니다.

4475 {
4476 return immutable_db_options_.fs.get();
4477}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetFullHistoryTsLow()

Status ROCKSDB_NAMESPACE::DBImpl::GetFullHistoryTsLow ( ColumnFamilyHandle * column_family,
std::string * ts_low )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 1909 번째 라인에서 정의되었습니다.

1910 {
1911 if (ts_low == nullptr) {
1912 return Status::InvalidArgument("ts_low is nullptr");
1913 }
1914 ColumnFamilyData* cfd = nullptr;
1915 if (column_family == nullptr) {
1916 cfd = default_cf_handle_->cfd();
1917 } else {
1918 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1919 assert(cfh != nullptr);
1920 cfd = cfh->cfd();
1921 }
1922 assert(cfd != nullptr && cfd->user_comparator() != nullptr);
1923 if (cfd->user_comparator()->timestamp_size() == 0) {
1924 return Status::InvalidArgument(
1925 "Timestamp is not enabled in this column family");
1926 }
1927 InstrumentedMutexLock l(&mutex_);
1928 *ts_low = cfd->GetFullHistoryTsLow();
1929 assert(ts_low->empty() ||
1930 cfd->user_comparator()->timestamp_size() == ts_low->size());
1931 return Status::OK();
1932}
virtual ColumnFamilyData * cfd() const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetImpl() [1/3]

Status ROCKSDB_NAMESPACE::DBImpl::GetImpl ( const ReadOptions & options,
const Slice & key,
GetImplOptions & get_impl_options )
virtual

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 2326 번째 라인에서 정의되었습니다.

2327 {
2328 assert(get_impl_options.value != nullptr ||
2329 get_impl_options.merge_operands != nullptr ||
2330 get_impl_options.columns != nullptr);
2331
2332 assert(get_impl_options.column_family);
2333
2334 if (read_options.timestamp) {
2335 const Status s = FailIfTsMismatchCf(get_impl_options.column_family,
2336 *(read_options.timestamp));
2337 if (!s.ok()) {
2338 return s;
2339 }
2340 } else {
2341 const Status s = FailIfCfHasTs(get_impl_options.column_family);
2342 if (!s.ok()) {
2343 return s;
2344 }
2345 }
2346
2347 // Clear the timestamps for returning results so that we can distinguish
2348 // between tombstone or key that has never been written
2349 if (get_impl_options.timestamp) {
2350 get_impl_options.timestamp->clear();
2351 }
2352
2353 GetWithTimestampReadCallback read_cb(0); // Will call Refresh
2354
2356 StopWatch sw(immutable_db_options_.clock, stats_, DB_GET);
2357 PERF_TIMER_GUARD(get_snapshot_time);
2358
2359 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(
2360 get_impl_options.column_family);
2361 auto cfd = cfh->cfd();
2362
2363 if (tracer_) {
2364 // TODO: This mutex should be removed later, to improve performance when
2365 // tracing is enabled.
2366 InstrumentedMutexLock lock(&trace_mutex_);
2367 if (tracer_) {
2368 // TODO: maybe handle the tracing status?
2369 tracer_->Get(get_impl_options.column_family, key).PermitUncheckedError();
2370 }
2371 }
2372
2373 if (get_impl_options.get_merge_operands_options != nullptr) {
2374 for (int i = 0; i < get_impl_options.get_merge_operands_options
2375 ->expected_max_number_of_operands;
2376 ++i) {
2377 get_impl_options.merge_operands[i].Reset();
2378 }
2379 }
2380
2381 // Acquire SuperVersion
2383 if (read_options.timestamp && read_options.timestamp->size() > 0) {
2384 const Status s =
2385 FailIfReadCollapsedHistory(cfd, sv, *(read_options.timestamp));
2386 if (!s.ok()) {
2388 return s;
2389 }
2390 }
2391
2392 TEST_SYNC_POINT_CALLBACK("DBImpl::GetImpl:AfterAcquireSv", nullptr);
2393 TEST_SYNC_POINT("DBImpl::GetImpl:1");
2394 TEST_SYNC_POINT("DBImpl::GetImpl:2");
2395
2396 SequenceNumber snapshot;
2397 if (read_options.snapshot != nullptr) {
2398 if (get_impl_options.callback) {
2399 // Already calculated based on read_options.snapshot
2400 snapshot = get_impl_options.callback->max_visible_seq();
2401 } else {
2402 snapshot =
2403 static_cast<const SnapshotImpl*>(read_options.snapshot)->number_;
2404 }
2405 } else {
2406 // Note that the snapshot is assigned AFTER referencing the super
2407 // version because otherwise a flush happening in between may compact away
2408 // data for the snapshot, so the reader would see neither data that was be
2409 // visible to the snapshot before compaction nor the newer data inserted
2410 // afterwards.
2411 snapshot = GetLastPublishedSequence();
2412 if (get_impl_options.callback) {
2413 // The unprep_seqs are not published for write unprepared, so it could be
2414 // that max_visible_seq is larger. Seek to the std::max of the two.
2415 // However, we still want our callback to contain the actual snapshot so
2416 // that it can do the correct visibility filtering.
2417 get_impl_options.callback->Refresh(snapshot);
2418
2419 // Internally, WriteUnpreparedTxnReadCallback::Refresh would set
2420 // max_visible_seq = max(max_visible_seq, snapshot)
2421 //
2422 // Currently, the commented out assert is broken by
2423 // InvalidSnapshotReadCallback, but if write unprepared recovery followed
2424 // the regular transaction flow, then this special read callback would not
2425 // be needed.
2426 //
2427 // assert(callback->max_visible_seq() >= snapshot);
2428 snapshot = get_impl_options.callback->max_visible_seq();
2429 }
2430 }
2431 // If timestamp is used, we use read callback to ensure <key,t,s> is returned
2432 // only if t <= read_opts.timestamp and s <= snapshot.
2433 // HACK: temporarily overwrite input struct field but restore
2434 SaveAndRestore<ReadCallback*> restore_callback(&get_impl_options.callback);
2435 const Comparator* ucmp = get_impl_options.column_family->GetComparator();
2436 assert(ucmp);
2437 if (ucmp->timestamp_size() > 0) {
2438 assert(!get_impl_options
2439 .callback); // timestamp with callback is not supported
2440 read_cb.Refresh(snapshot);
2441 get_impl_options.callback = &read_cb;
2442 }
2443 TEST_SYNC_POINT("DBImpl::GetImpl:3");
2444 TEST_SYNC_POINT("DBImpl::GetImpl:4");
2445
2446 // Prepare to store a list of merge operations if merge occurs.
2447 MergeContext merge_context;
2448 merge_context.get_merge_operands_options =
2449 get_impl_options.get_merge_operands_options;
2450 SequenceNumber max_covering_tombstone_seq = 0;
2451
2452 Status s;
2453 // First look in the memtable, then in the immutable memtable (if any).
2454 // s is both in/out. When in, s could either be OK or MergeInProgress.
2455 // merge_operands will contain the sequence of merges in the latter case.
2456 LookupKey lkey(key, snapshot, read_options.timestamp);
2457 PERF_TIMER_STOP(get_snapshot_time);
2458
2459 bool skip_memtable = (read_options.read_tier == kPersistedTier &&
2460 has_unpersisted_data_.load(std::memory_order_relaxed));
2461 bool done = false;
2462 std::string* timestamp =
2463 ucmp->timestamp_size() > 0 ? get_impl_options.timestamp : nullptr;
2464 if (!skip_memtable) {
2465 // Get value associated with key
2466 if (get_impl_options.get_value) {
2467 if (sv->mem->Get(
2468 lkey,
2469 get_impl_options.value ? get_impl_options.value->GetSelf()
2470 : nullptr,
2471 get_impl_options.columns, timestamp, &s, &merge_context,
2472 &max_covering_tombstone_seq, read_options,
2473 false /* immutable_memtable */, get_impl_options.callback,
2474 get_impl_options.is_blob_index)) {
2475 done = true;
2476
2477 if (get_impl_options.value) {
2478 get_impl_options.value->PinSelf();
2479 }
2480
2481 RecordTick(stats_, MEMTABLE_HIT);
2482 } else if ((s.ok() || s.IsMergeInProgress()) &&
2483 sv->imm->Get(lkey,
2484 get_impl_options.value
2485 ? get_impl_options.value->GetSelf()
2486 : nullptr,
2487 get_impl_options.columns, timestamp, &s,
2488 &merge_context, &max_covering_tombstone_seq,
2489 read_options, get_impl_options.callback,
2490 get_impl_options.is_blob_index)) {
2491 done = true;
2492
2493 if (get_impl_options.value) {
2494 get_impl_options.value->PinSelf();
2495 }
2496
2497 RecordTick(stats_, MEMTABLE_HIT);
2498 }
2499 } else {
2500 // Get Merge Operands associated with key, Merge Operands should not be
2501 // merged and raw values should be returned to the user.
2502 if (sv->mem->Get(lkey, /*value=*/nullptr, /*columns=*/nullptr,
2503 /*timestamp=*/nullptr, &s, &merge_context,
2504 &max_covering_tombstone_seq, read_options,
2505 false /* immutable_memtable */, nullptr, nullptr,
2506 false)) {
2507 done = true;
2508 RecordTick(stats_, MEMTABLE_HIT);
2509 } else if ((s.ok() || s.IsMergeInProgress()) &&
2510 sv->imm->GetMergeOperands(lkey, &s, &merge_context,
2511 &max_covering_tombstone_seq,
2512 read_options)) {
2513 done = true;
2514 RecordTick(stats_, MEMTABLE_HIT);
2515 }
2516 }
2517 if (!s.ok() && !s.IsMergeInProgress() && !s.IsNotFound()) {
2518 assert(done);
2520 return s;
2521 }
2522 }
2523 TEST_SYNC_POINT("DBImpl::GetImpl:PostMemTableGet:0");
2524 TEST_SYNC_POINT("DBImpl::GetImpl:PostMemTableGet:1");
2525 PinnedIteratorsManager pinned_iters_mgr;
2526 if (!done) {
2527 PERF_TIMER_GUARD(get_from_output_files_time);
2528 sv->current->Get(
2529 read_options, lkey, get_impl_options.value, get_impl_options.columns,
2530 timestamp, &s, &merge_context, &max_covering_tombstone_seq,
2531 &pinned_iters_mgr,
2532 get_impl_options.get_value ? get_impl_options.value_found : nullptr,
2533 nullptr, nullptr,
2534 get_impl_options.get_value ? get_impl_options.callback : nullptr,
2535 get_impl_options.get_value ? get_impl_options.is_blob_index : nullptr,
2536 get_impl_options.get_value);
2537 RecordTick(stats_, MEMTABLE_MISS);
2538 }
2539
2540 {
2541 PERF_TIMER_GUARD(get_post_process_time);
2542
2543 RecordTick(stats_, NUMBER_KEYS_READ);
2544 size_t size = 0;
2545 if (s.ok()) {
2546 const auto& merge_threshold = read_options.merge_operand_count_threshold;
2547 if (merge_threshold.has_value() &&
2548 merge_context.GetNumOperands() > merge_threshold.value()) {
2549 s = Status::OkMergeOperandThresholdExceeded();
2550 }
2551
2552 if (get_impl_options.get_value) {
2553 if (get_impl_options.value) {
2554 size = get_impl_options.value->size();
2555 } else if (get_impl_options.columns) {
2556 size = get_impl_options.columns->serialized_size();
2557 }
2558 } else {
2559 // Return all merge operands for get_impl_options.key
2560 *get_impl_options.number_of_operands =
2561 static_cast<int>(merge_context.GetNumOperands());
2562 if (*get_impl_options.number_of_operands >
2563 get_impl_options.get_merge_operands_options
2564 ->expected_max_number_of_operands) {
2565 s = Status::Incomplete(
2566 Status::SubCode::KMergeOperandsInsufficientCapacity);
2567 } else {
2568 // Each operand depends on one of the following resources: `sv`,
2569 // `pinned_iters_mgr`, or `merge_context`. It would be crazy expensive
2570 // to reference `sv` for each operand relying on it because `sv` is
2571 // (un)ref'd in all threads using the DB. Furthermore, we do not track
2572 // on which resource each operand depends.
2573 //
2574 // To solve this, we bundle the resources in a `GetMergeOperandsState`
2575 // and manage them with a `SharedCleanablePtr` shared among the
2576 // `PinnableSlice`s we return. This bundle includes one `sv` reference
2577 // and ownership of the `merge_context` and `pinned_iters_mgr`
2578 // objects.
2579 bool ref_sv = ShouldReferenceSuperVersion(merge_context);
2580 if (ref_sv) {
2581 assert(!merge_context.GetOperands().empty());
2582 SharedCleanablePtr shared_cleanable;
2583 GetMergeOperandsState* state = nullptr;
2584 state = new GetMergeOperandsState();
2585 state->merge_context = std::move(merge_context);
2586 state->pinned_iters_mgr = std::move(pinned_iters_mgr);
2587
2588 sv->Ref();
2589
2590 state->sv_handle = new SuperVersionHandle(
2591 this, &mutex_, sv,
2593
2594 shared_cleanable.Allocate();
2595 shared_cleanable->RegisterCleanup(CleanupGetMergeOperandsState,
2596 state /* arg1 */,
2597 nullptr /* arg2 */);
2598 for (size_t i = 0; i < state->merge_context.GetOperands().size();
2599 ++i) {
2600 const Slice& sl = state->merge_context.GetOperands()[i];
2601 size += sl.size();
2602
2603 get_impl_options.merge_operands->PinSlice(
2604 sl, nullptr /* cleanable */);
2605 if (i == state->merge_context.GetOperands().size() - 1) {
2606 shared_cleanable.MoveAsCleanupTo(
2607 get_impl_options.merge_operands);
2608 } else {
2609 shared_cleanable.RegisterCopyWith(
2610 get_impl_options.merge_operands);
2611 }
2612 get_impl_options.merge_operands++;
2613 }
2614 } else {
2615 for (const Slice& sl : merge_context.GetOperands()) {
2616 size += sl.size();
2617 get_impl_options.merge_operands->PinSelf(sl);
2618 get_impl_options.merge_operands++;
2619 }
2620 }
2621 }
2622 }
2623 RecordTick(stats_, BYTES_READ, size);
2624 PERF_COUNTER_ADD(get_read_bytes, size);
2625 }
2626
2628
2629 RecordInHistogram(stats_, BYTES_PER_READ, size);
2630 }
2631 return s;
2632}
Status FailIfReadCollapsedHistory(const ColumnFamilyData *cfd, const SuperVersion *sv, const Slice &ts) const
Definition db_impl.h:3142
bool ShouldReferenceSuperVersion(const MergeContext &merge_context)
Definition db_impl.cc:2298
#define PERF_TIMER_GUARD(metric)
#define PERF_COUNTER_ADD(metric, value)
#define PERF_TIMER_STOP(metric)
#define PERF_CPU_TIMER_GUARD(metric, clock)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetImpl() [2/3]

Status ROCKSDB_NAMESPACE::DBImpl::GetImpl ( const ReadOptions & read_options,
ColumnFamilyHandle * column_family,
const Slice & key,
PinnableSlice * value )

db_impl.cc 파일의 2160 번째 라인에서 정의되었습니다.

2162 {
2163 return GetImpl(read_options, column_family, key, value,
2164 /*timestamp=*/nullptr);
2165}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetImpl() [3/3]

Status ROCKSDB_NAMESPACE::DBImpl::GetImpl ( const ReadOptions & read_options,
ColumnFamilyHandle * column_family,
const Slice & key,
PinnableSlice * value,
std::string * timestamp )

db_impl.cc 파일의 2189 번째 라인에서 정의되었습니다.

2191 {
2192 GetImplOptions get_impl_options;
2193 get_impl_options.column_family = column_family;
2194 get_impl_options.value = value;
2195 get_impl_options.timestamp = timestamp;
2196
2197 Status s = GetImpl(read_options, key, get_impl_options);
2198 return s;
2199}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetIntProperty() [1/2]

bool ROCKSDB_NAMESPACE::DBImpl::GetIntProperty ( ColumnFamilyHandle * column_family,
const Slice & property,
uint64_t * value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4570 번째 라인에서 정의되었습니다.

4571 {
4572 const DBPropertyInfo* property_info = GetPropertyInfo(property);
4573 if (property_info == nullptr || property_info->handle_int == nullptr) {
4574 return false;
4575 }
4576 auto cfd =
4577 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
4578 return GetIntPropertyInternal(cfd, *property_info, false, value);
4579}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetIntProperty() [2/2]

virtual bool ROCKSDB_NAMESPACE::DB::GetIntProperty ( const Slice & property,
uint64_t * value )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1403 번째 라인에서 정의되었습니다.

1403 {
1404 return GetIntProperty(DefaultColumnFamily(), property, value);
1405 }
bool GetIntProperty(ColumnFamilyHandle *column_family, const Slice &property, uint64_t *value) override
Definition db_impl.cc:4570

◆ GetIntPropertyInternal()

bool ROCKSDB_NAMESPACE::DBImpl::GetIntPropertyInternal ( ColumnFamilyData * cfd,
const DBPropertyInfo & property_info,
bool is_locked,
uint64_t * value )
private

db_impl.cc 파일의 4581 번째 라인에서 정의되었습니다.

4583 {
4584 assert(property_info.handle_int != nullptr);
4585 if (!property_info.need_out_of_mutex) {
4586 if (is_locked) {
4587 mutex_.AssertHeld();
4588 return cfd->internal_stats()->GetIntProperty(property_info, value, this);
4589 } else {
4590 InstrumentedMutexLock l(&mutex_);
4591 return cfd->internal_stats()->GetIntProperty(property_info, value, this);
4592 }
4593 } else {
4594 SuperVersion* sv = nullptr;
4595 if (is_locked) {
4596 mutex_.Unlock();
4597 }
4598 sv = GetAndRefSuperVersion(cfd);
4599
4600 bool ret = cfd->internal_stats()->GetIntPropertyOutOfMutex(
4601 property_info, sv->current, value);
4602
4604 if (is_locked) {
4605 mutex_.Lock();
4606 }
4607
4608 return ret;
4609 }
4610}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLastPublishedSequence()

virtual SequenceNumber ROCKSDB_NAMESPACE::DBImpl::GetLastPublishedSequence ( ) const
inlinevirtual

db_impl.h 파일의 686 번째 라인에서 정의되었습니다.

686 {
687 if (last_seq_same_as_publish_seq_) {
688 return versions_->LastSequence();
689 } else {
690 return versions_->LastPublishedSequence();
691 }
692 }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLatestSequenceForKey()

Status ROCKSDB_NAMESPACE::DBImpl::GetLatestSequenceForKey ( SuperVersion * sv,
const Slice & key,
bool cache_only,
SequenceNumber lower_bound_seq,
SequenceNumber * seq,
std::string * timestamp,
bool * found_record_for_key,
bool * is_blob_index )

db_impl.cc 파일의 5736 번째 라인에서 정의되었습니다.

5739 {
5740 Status s;
5741 MergeContext merge_context;
5742 SequenceNumber max_covering_tombstone_seq = 0;
5743
5744 // TODO: plumb Env::IOActivity, Env::IOPriority
5745 ReadOptions read_options;
5746 SequenceNumber current_seq = versions_->LastSequence();
5747
5748 ColumnFamilyData* cfd = sv->cfd;
5749 assert(cfd);
5750 const Comparator* const ucmp = cfd->user_comparator();
5751 assert(ucmp);
5752 size_t ts_sz = ucmp->timestamp_size();
5753 std::string ts_buf;
5754 if (ts_sz > 0) {
5755 assert(timestamp);
5756 ts_buf.assign(ts_sz, '\xff');
5757 } else {
5758 assert(!timestamp);
5759 }
5760 Slice ts(ts_buf);
5761
5762 LookupKey lkey(key, current_seq, ts_sz == 0 ? nullptr : &ts);
5763
5764 *seq = kMaxSequenceNumber;
5765 *found_record_for_key = false;
5766
5767 // Check if there is a record for this key in the latest memtable
5768 sv->mem->Get(lkey, /*value=*/nullptr, /*columns=*/nullptr, timestamp, &s,
5769 &merge_context, &max_covering_tombstone_seq, seq, read_options,
5770 false /* immutable_memtable */, nullptr /*read_callback*/,
5771 is_blob_index);
5772
5773 if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
5774 // unexpected error reading memtable.
5776 "Unexpected status returned from MemTable::Get: %s\n",
5777 s.ToString().c_str());
5778
5779 return s;
5780 }
5781 assert(!ts_sz ||
5782 (*seq != kMaxSequenceNumber &&
5783 *timestamp != std::string(ts_sz, '\xff')) ||
5784 (*seq == kMaxSequenceNumber && timestamp->empty()));
5785
5786 TEST_SYNC_POINT_CALLBACK("DBImpl::GetLatestSequenceForKey:mem", timestamp);
5787
5788 if (*seq != kMaxSequenceNumber) {
5789 // Found a sequence number, no need to check immutable memtables
5790 *found_record_for_key = true;
5791 return Status::OK();
5792 }
5793
5794 SequenceNumber lower_bound_in_mem = sv->mem->GetEarliestSequenceNumber();
5795 if (lower_bound_in_mem != kMaxSequenceNumber &&
5796 lower_bound_in_mem < lower_bound_seq) {
5797 *found_record_for_key = false;
5798 return Status::OK();
5799 }
5800
5801 // Check if there is a record for this key in the immutable memtables
5802 sv->imm->Get(lkey, /*value=*/nullptr, /*columns=*/nullptr, timestamp, &s,
5803 &merge_context, &max_covering_tombstone_seq, seq, read_options,
5804 nullptr /*read_callback*/, is_blob_index);
5805
5806 if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
5807 // unexpected error reading memtable.
5809 "Unexpected status returned from MemTableList::Get: %s\n",
5810 s.ToString().c_str());
5811
5812 return s;
5813 }
5814
5815 assert(!ts_sz ||
5816 (*seq != kMaxSequenceNumber &&
5817 *timestamp != std::string(ts_sz, '\xff')) ||
5818 (*seq == kMaxSequenceNumber && timestamp->empty()));
5819
5820 if (*seq != kMaxSequenceNumber) {
5821 // Found a sequence number, no need to check memtable history
5822 *found_record_for_key = true;
5823 return Status::OK();
5824 }
5825
5826 SequenceNumber lower_bound_in_imm = sv->imm->GetEarliestSequenceNumber();
5827 if (lower_bound_in_imm != kMaxSequenceNumber &&
5828 lower_bound_in_imm < lower_bound_seq) {
5829 *found_record_for_key = false;
5830 return Status::OK();
5831 }
5832
5833 // Check if there is a record for this key in the immutable memtables
5834 sv->imm->GetFromHistory(lkey, /*value=*/nullptr, /*columns=*/nullptr,
5835 timestamp, &s, &merge_context,
5836 &max_covering_tombstone_seq, seq, read_options,
5837 is_blob_index);
5838
5839 if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
5840 // unexpected error reading memtable.
5843 "Unexpected status returned from MemTableList::GetFromHistory: %s\n",
5844 s.ToString().c_str());
5845
5846 return s;
5847 }
5848
5849 assert(!ts_sz ||
5850 (*seq != kMaxSequenceNumber &&
5851 *timestamp != std::string(ts_sz, '\xff')) ||
5852 (*seq == kMaxSequenceNumber && timestamp->empty()));
5853
5854 if (*seq != kMaxSequenceNumber) {
5855 // Found a sequence number, no need to check SST files
5856 assert(0 == ts_sz || *timestamp != std::string(ts_sz, '\xff'));
5857 *found_record_for_key = true;
5858 return Status::OK();
5859 }
5860
5861 // We could do a sv->imm->GetEarliestSequenceNumber(/*include_history*/ true)
5862 // check here to skip the history if possible. But currently the caller
5863 // already does that. Maybe we should move the logic here later.
5864
5865 // TODO(agiardullo): possible optimization: consider checking cached
5866 // SST files if cache_only=true?
5867 if (!cache_only) {
5868 // Check tables
5869 PinnedIteratorsManager pinned_iters_mgr;
5870 sv->current->Get(read_options, lkey, /*value=*/nullptr, /*columns=*/nullptr,
5871 timestamp, &s, &merge_context, &max_covering_tombstone_seq,
5872 &pinned_iters_mgr, nullptr /* value_found */,
5873 found_record_for_key, seq, nullptr /*read_callback*/,
5874 is_blob_index);
5875
5876 if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
5877 // unexpected error reading SST files
5879 "Unexpected status returned from Version::Get: %s\n",
5880 s.ToString().c_str());
5881 }
5882 }
5883
5884 return s;
5885}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLatestSequenceNumber()

SequenceNumber ROCKSDB_NAMESPACE::DBImpl::GetLatestSequenceNumber ( ) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 1901 번째 라인에서 정의되었습니다.

1901 {
1902 return versions_->LastSequence();
1903}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLiveFiles()

Status ROCKSDB_NAMESPACE::DBImpl::GetLiveFiles ( std::vector< std::string > & ret,
uint64_t * manifest_file_size,
bool flush_memtable = true )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_filesnapshot.cc 파일의 37 번째 라인에서 정의되었습니다.

38 {
39 *manifest_file_size = 0;
40
41 mutex_.Lock();
42
43 if (flush_memtable) {
44 Status status = FlushForGetLiveFiles();
45 if (!status.ok()) {
46 mutex_.Unlock();
47 ROCKS_LOG_ERROR(immutable_db_options_.info_log, "Cannot Flush data %s\n",
48 status.ToString().c_str());
49 return status;
50 }
51 }
52
53 // Make a set of all of the live table and blob files
54 std::vector<uint64_t> live_table_files;
55 std::vector<uint64_t> live_blob_files;
56 for (auto cfd : *versions_->GetColumnFamilySet()) {
57 if (cfd->IsDropped()) {
58 continue;
59 }
60 cfd->current()->AddLiveFiles(&live_table_files, &live_blob_files);
61 }
62
63 ret.clear();
64 ret.reserve(live_table_files.size() + live_blob_files.size() +
65 3); // for CURRENT + MANIFEST + OPTIONS
66
67 // create names of the live files. The names are not absolute
68 // paths, instead they are relative to dbname_.
69 for (const auto& table_file_number : live_table_files) {
70 ret.emplace_back(MakeTableFileName("", table_file_number));
71 }
72
73 for (const auto& blob_file_number : live_blob_files) {
74 ret.emplace_back(BlobFileName("", blob_file_number));
75 }
76
77 ret.emplace_back(CurrentFileName(""));
78 ret.emplace_back(DescriptorFileName("", versions_->manifest_file_number()));
79 // The OPTIONS file number is zero in read-write mode when OPTIONS file
80 // writing failed and the DB was configured with
81 // `fail_if_options_file_error == false`. In read-only mode the OPTIONS file
82 // number is zero when no OPTIONS file exist at all. In those cases we do not
83 // record any OPTIONS file in the live file list.
84 if (versions_->options_file_number() != 0) {
85 ret.emplace_back(OptionsFileName("", versions_->options_file_number()));
86 }
87
88 // find length of manifest file while holding the mutex lock
89 *manifest_file_size = versions_->manifest_file_size();
90
91 mutex_.Unlock();
92 return Status::OK();
93}
virtual Status FlushForGetLiveFiles()
std::string OptionsFileName(uint64_t file_num)
Definition filename.cc:227
std::string CurrentFileName(const std::string &dbname)
Definition filename.cc:177
std::string DescriptorFileName(uint64_t number)
Definition filename.cc:165
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLiveFilesChecksumInfo()

Status ROCKSDB_NAMESPACE::DBImpl::GetLiveFilesChecksumInfo ( FileChecksumList * checksum_list)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 5107 번째 라인에서 정의되었습니다.

5107 {
5108 InstrumentedMutexLock l(&mutex_);
5109 return versions_->GetLiveFilesChecksumInfo(checksum_list);
5110}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLiveFilesMetaData()

void ROCKSDB_NAMESPACE::DBImpl::GetLiveFilesMetaData ( std::vector< LiveFileMetaData > * metadata)
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 5102 번째 라인에서 정의되었습니다.

5102 {
5103 InstrumentedMutexLock l(&mutex_);
5104 versions_->GetLiveFilesMetaData(metadata);
5105}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLiveFilesStorageInfo()

Status ROCKSDB_NAMESPACE::DBImpl::GetLiveFilesStorageInfo ( const LiveFilesStorageInfoOptions & opts,
std::vector< LiveFileStorageInfo > * files )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_filesnapshot.cc 파일의 199 번째 라인에서 정의되었습니다.

201 {
202 // To avoid returning partial results, only move results to files on success.
203 assert(files);
204 files->clear();
205 std::vector<LiveFileStorageInfo> results;
206
207 // NOTE: This implementation was largely migrated from Checkpoint.
208
209 Status s;
210 VectorWalPtr live_wal_files;
211 bool flush_memtable = true;
213 if (opts.wal_size_for_flush == std::numeric_limits<uint64_t>::max()) {
214 flush_memtable = false;
215 } else if (opts.wal_size_for_flush > 0) {
216 // FIXME: avoid querying the filesystem for current WAL state
217 // If the outstanding WAL files are small, we skip the flush.
218 // Don't take archived log size into account when calculating wal
219 // size for flush, and don't need to verify consistency with manifest
220 // here & now.
221 s = wal_manager_.GetSortedWalFiles(live_wal_files,
222 /* need_seqnos */ false,
223 /*include_archived*/ false);
224
225 if (!s.ok()) {
226 return s;
227 }
228
229 // Don't flush column families if total log size is smaller than
230 // log_size_for_flush. We copy the log files instead.
231 // We may be able to cover 2PC case too.
232 uint64_t total_wal_size = 0;
233 for (auto& wal : live_wal_files) {
234 assert(wal->Type() == kAliveLogFile);
235 total_wal_size += wal->SizeFileBytes();
236 }
237 if (total_wal_size < opts.wal_size_for_flush) {
238 flush_memtable = false;
239 }
240 live_wal_files.clear();
241 }
242 }
243
244 // This is a modified version of GetLiveFiles, to get access to more
245 // metadata.
246 mutex_.Lock();
247 if (flush_memtable) {
248 bool wal_locked = lock_wal_count_ > 0;
249 if (wal_locked) {
251 "Can't FlushForGetLiveFiles while WAL is locked");
252 } else {
253 Status status = FlushForGetLiveFiles();
254 if (!status.ok()) {
255 mutex_.Unlock();
257 "Cannot Flush data %s\n", status.ToString().c_str());
258 return status;
259 }
260 }
261 }
262
263 // Make a set of all of the live table and blob files
264 for (auto cfd : *versions_->GetColumnFamilySet()) {
265 if (cfd->IsDropped()) {
266 continue;
267 }
268 VersionStorageInfo& vsi = *cfd->current()->storage_info();
269 auto& cf_paths = cfd->ioptions()->cf_paths;
270
271 auto GetDir = [&](size_t path_id) {
272 // Matching TableFileName() behavior
273 if (path_id >= cf_paths.size()) {
274 assert(false);
275 return cf_paths.back().path;
276 } else {
277 return cf_paths[path_id].path;
278 }
279 };
280
281 for (int level = 0; level < vsi.num_levels(); ++level) {
282 const auto& level_files = vsi.LevelFiles(level);
283 for (const auto& meta : level_files) {
284 assert(meta);
285
286 results.emplace_back();
287 LiveFileStorageInfo& info = results.back();
288
289 info.relative_filename = MakeTableFileName(meta->fd.GetNumber());
290 info.directory = GetDir(meta->fd.GetPathId());
291 info.file_number = meta->fd.GetNumber();
292 info.file_type = kTableFile;
293 info.size = meta->fd.GetFileSize();
294 if (opts.include_checksum_info) {
295 info.file_checksum_func_name = meta->file_checksum_func_name;
296 info.file_checksum = meta->file_checksum;
297 if (info.file_checksum_func_name.empty()) {
298 info.file_checksum_func_name = kUnknownFileChecksumFuncName;
299 info.file_checksum = kUnknownFileChecksum;
300 }
301 }
302 info.temperature = meta->temperature;
303 }
304 }
305 const auto& blob_files = vsi.GetBlobFiles();
306 for (const auto& meta : blob_files) {
307 assert(meta);
308
309 results.emplace_back();
310 LiveFileStorageInfo& info = results.back();
311
312 info.relative_filename = BlobFileName(meta->GetBlobFileNumber());
313 info.directory = GetDir(/* path_id */ 0);
314 info.file_number = meta->GetBlobFileNumber();
315 info.file_type = kBlobFile;
316 info.size = meta->GetBlobFileSize();
317 if (opts.include_checksum_info) {
318 info.file_checksum_func_name = meta->GetChecksumMethod();
319 info.file_checksum = meta->GetChecksumValue();
320 if (info.file_checksum_func_name.empty()) {
321 info.file_checksum_func_name = kUnknownFileChecksumFuncName;
322 info.file_checksum = kUnknownFileChecksum;
323 }
324 }
325 // TODO?: info.temperature
326 }
327 }
328
329 // Capture some final info before releasing mutex
330 const uint64_t manifest_number = versions_->manifest_file_number();
331 const uint64_t manifest_size = versions_->manifest_file_size();
332 const uint64_t options_number = versions_->options_file_number();
333 const uint64_t options_size = versions_->options_file_size_;
334 const uint64_t min_log_num = MinLogNumberToKeep();
335 // Ensure consistency with manifest for track_and_verify_wals_in_manifest
336 const uint64_t max_log_num = logfile_number_;
337
338 mutex_.Unlock();
339
340 std::string manifest_fname = DescriptorFileName(manifest_number);
341 { // MANIFEST
342 results.emplace_back();
343 LiveFileStorageInfo& info = results.back();
344
345 info.relative_filename = manifest_fname;
346 info.directory = GetName();
347 info.file_number = manifest_number;
348 info.file_type = kDescriptorFile;
349 info.size = manifest_size;
350 info.trim_to_size = true;
351 if (opts.include_checksum_info) {
352 info.file_checksum_func_name = kUnknownFileChecksumFuncName;
353 info.file_checksum = kUnknownFileChecksum;
354 }
355 }
356
357 { // CURRENT
358 results.emplace_back();
359 LiveFileStorageInfo& info = results.back();
360
361 info.relative_filename = kCurrentFileName;
362 info.directory = GetName();
363 info.file_type = kCurrentFile;
364 // CURRENT could be replaced so we have to record the contents as needed.
365 info.replacement_contents = manifest_fname + "\n";
366 info.size = manifest_fname.size() + 1;
367 if (opts.include_checksum_info) {
368 info.file_checksum_func_name = kUnknownFileChecksumFuncName;
369 info.file_checksum = kUnknownFileChecksum;
370 }
371 }
372
373 // The OPTIONS file number is zero in read-write mode when OPTIONS file
374 // writing failed and the DB was configured with
375 // `fail_if_options_file_error == false`. In read-only mode the OPTIONS file
376 // number is zero when no OPTIONS file exist at all. In those cases we do not
377 // record any OPTIONS file in the live file list.
378 if (options_number != 0) {
379 results.emplace_back();
380 LiveFileStorageInfo& info = results.back();
381
382 info.relative_filename = OptionsFileName(options_number);
383 info.directory = GetName();
384 info.file_number = options_number;
385 info.file_type = kOptionsFile;
386 info.size = options_size;
387 if (opts.include_checksum_info) {
388 info.file_checksum_func_name = kUnknownFileChecksumFuncName;
389 info.file_checksum = kUnknownFileChecksum;
390 }
391 }
392
393 // Some legacy testing stuff TODO: carefully clean up obsolete parts
394 TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:FlushDone");
395
396 TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:SavedLiveFiles1");
397 TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:SavedLiveFiles2");
398
399 if (s.ok()) {
400 // FlushWAL is required to ensure we can physically copy everything
401 // logically written to the WAL. (Sync not strictly required for
402 // active WAL to be copied rather than hard linked, even when
403 // Checkpoint guarantees that the copied-to file is sync-ed. Plus we can't
404 // help track_and_verify_wals_in_manifest after manifest_size is
405 // already determined.)
406 s = FlushWAL(/*sync=*/false);
407 if (s.IsNotSupported()) { // read-only DB or similar
408 s = Status::OK();
409 }
410 }
411
412 TEST_SYNC_POINT("CheckpointImpl::CreateCustomCheckpoint:AfterGetLive1");
413 TEST_SYNC_POINT("CheckpointImpl::CreateCustomCheckpoint:AfterGetLive2");
414
415 // Even after WAL flush, there could be multiple WALs that are not
416 // fully synced. Although the output DB of a Checkpoint or Backup needs
417 // to be fully synced on return, we don't strictly need to sync this
418 // DB (the input DB). If we allow Checkpoint to hard link an inactive
419 // WAL that isn't fully synced, that could result in an insufficiently
420 // sync-ed Checkpoint. Here we get the set of WALs that are potentially
421 // unsynced or still being written to, to prevent them from being hard
422 // linked. Enforcing max_log_num from above ensures any new WALs after
423 // GetOpenWalSizes() and before GetSortedWalFiles() are not included in
424 // the results.
425 // NOTE: we might still hard link a file that is open for writing, even
426 // if we don't do any more writes to it.
427 //
428 // In a step toward reducing unnecessary file metadata queries, we also
429 // get and use our known flushed sizes for those WALs.
430 // FIXME: eventually we should not be using filesystem queries at all for
431 // the required set of WAL files.
432 //
433 // However for recycled log files, we just copy the whole file,
434 // for better or worse.
435 //
436 std::map<uint64_t, uint64_t> open_wal_number_to_size;
437 bool recycling_log_files = immutable_db_options_.recycle_log_file_num > 0;
438 if (s.ok() && !recycling_log_files) {
439 s = GetOpenWalSizes(open_wal_number_to_size);
440 }
441
442 // [old comment] If we have more than one column family, we also need to get
443 // WAL files.
444 if (s.ok()) {
445 // FIXME: avoid querying the filesystem for current WAL state
446 s = GetSortedWalFilesImpl(live_wal_files,
447 /* need_seqnos */ false);
448 }
449 if (!s.ok()) {
450 return s;
451 }
452
453 size_t wal_count = live_wal_files.size();
454 // Link WAL files. Copy exact size of last one because it is the only one
455 // that has changes after the last flush.
456 auto wal_dir = immutable_db_options_.GetWalDir();
457 for (size_t i = 0; s.ok() && i < wal_count; ++i) {
458 if ((live_wal_files[i]->Type() == kAliveLogFile) &&
459 (!flush_memtable || live_wal_files[i]->LogNumber() >= min_log_num) &&
460 live_wal_files[i]->LogNumber() <= max_log_num) {
461 results.emplace_back();
462 LiveFileStorageInfo& info = results.back();
463 auto f = live_wal_files[i]->PathName();
464 assert(!f.empty() && f[0] == '/');
465 info.relative_filename = f.substr(1);
466 info.directory = wal_dir;
467 info.file_number = live_wal_files[i]->LogNumber();
468 info.file_type = kWalFile;
469 if (recycling_log_files) {
470 info.size = live_wal_files[i]->SizeFileBytes();
471 // Recyclable WAL files must be copied instead of hard linked
472 info.trim_to_size = true;
473 } else {
474 auto it = open_wal_number_to_size.find(info.file_number);
475 if (it == open_wal_number_to_size.end()) {
476 // Known fully synced and no future writes (in part from
477 // max_log_num check). Ok to hard link
478 info.size = live_wal_files[i]->SizeFileBytes();
479 assert(!info.trim_to_size);
480 } else {
481 // Marked as (possibly) still open -> use our known flushed size
482 // and force file copy instead of hard link
483 info.size = it->second;
484 info.trim_to_size = true;
485 // FIXME: this is needed as long as db_stress uses
486 // SetReadUnsyncedData(false), because it will only be able to
487 // copy the synced portion of the WAL, which under
488 // SetReadUnsyncedData(false) is given by the reported file size.
489 info.size = std::min(info.size, live_wal_files[i]->SizeFileBytes());
490 }
491 }
492 if (opts.include_checksum_info) {
493 info.file_checksum_func_name = kUnknownFileChecksumFuncName;
494 info.file_checksum = kUnknownFileChecksum;
495 }
496 }
497 }
498
499 if (s.ok()) {
500 // Only move results to output on success.
501 *files = std::move(results);
502 }
503 return s;
504}
Status GetOpenWalSizes(std::map< uint64_t, uint64_t > &number_to_size)
Definition db_impl.cc:1585
Status GetSortedWalFilesImpl(VectorWalPtr &files, bool need_seqnos)
Status GetSortedWalFiles(VectorWalPtr &files, bool need_seqnos=true, bool include_archived=true)
std::vector< std::unique_ptr< WalFile > > VectorWalPtr
constexpr char kUnknownFileChecksumFuncName[]
const std::string kCurrentFileName
Definition filename.cc:26
constexpr char kUnknownFileChecksum[]
results(version_str, config)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetLogSizeAndMaybeTruncate()

Status ROCKSDB_NAMESPACE::DBImpl::GetLogSizeAndMaybeTruncate ( uint64_t wal_number,
bool truncate,
LogFileNumberSize * log )
private

db_impl_open.cc 파일의 1577 번째 라인에서 정의되었습니다.

1578 {
1579 LogFileNumberSize log(wal_number);
1580 std::string fname =
1582 Status s;
1583 // This gets the appear size of the wals, not including preallocated space.
1584 s = env_->GetFileSize(fname, &log.size);
1585 TEST_SYNC_POINT_CALLBACK("DBImpl::GetLogSizeAndMaybeTruncate:0", /*arg=*/&s);
1586 if (s.ok() && truncate) {
1587 std::unique_ptr<FSWritableFile> last_log;
1588 Status truncate_status = fs_->ReopenWritableFile(
1589 fname,
1590 fs_->OptimizeForLogWrite(
1591 file_options_,
1592 BuildDBOptions(immutable_db_options_, mutable_db_options_)),
1593 &last_log, nullptr);
1594 if (truncate_status.ok()) {
1595 truncate_status = last_log->Truncate(log.size, IOOptions(), nullptr);
1596 }
1597 if (truncate_status.ok()) {
1598 truncate_status = last_log->Close(IOOptions(), nullptr);
1599 }
1600 // Not a critical error if fail to truncate.
1601 if (!truncate_status.ok() && !truncate_status.IsNotSupported()) {
1603 "Failed to truncate log #%" PRIu64 ": %s", wal_number,
1604 truncate_status.ToString().c_str());
1605 }
1606 }
1607 if (log_ptr) {
1608 *log_ptr = log;
1609 }
1610 return s;
1611}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetMapProperty() [1/2]

bool ROCKSDB_NAMESPACE::DBImpl::GetMapProperty ( ColumnFamilyHandle * column_family,
const Slice & property,
std::map< std::string, std::string > * value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4546 번째 라인에서 정의되었습니다.

4548 {
4549 const DBPropertyInfo* property_info = GetPropertyInfo(property);
4550 value->clear();
4551 auto cfd =
4552 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
4553 if (property_info == nullptr) {
4554 return false;
4555 } else if (property_info->handle_map) {
4556 if (property_info->need_out_of_mutex) {
4557 return cfd->internal_stats()->GetMapProperty(*property_info, property,
4558 value);
4559 } else {
4560 InstrumentedMutexLock l(&mutex_);
4561 return cfd->internal_stats()->GetMapProperty(*property_info, property,
4562 value);
4563 }
4564 }
4565 // If we reach this point it means that handle_map is not provided for the
4566 // requested property
4567 return false;
4568}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetMapProperty() [2/2]

virtual bool ROCKSDB_NAMESPACE::DB::GetMapProperty ( const Slice & property,
std::map< std::string, std::string > * value )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1351 번째 라인에서 정의되었습니다.

1352 {
1353 return GetMapProperty(DefaultColumnFamily(), property, value);
1354 }
bool GetMapProperty(ColumnFamilyHandle *column_family, const Slice &property, std::map< std::string, std::string > *value) override
Definition db_impl.cc:4546

◆ GetMaxTotalWalSize()

uint64_t ROCKSDB_NAMESPACE::DBImpl::GetMaxTotalWalSize ( ) const
private

db_impl_write.cc 파일의 2087 번째 라인에서 정의되었습니다.

2087 {
2088 uint64_t max_total_wal_size =
2089 max_total_wal_size_.load(std::memory_order_acquire);
2090 if (max_total_wal_size > 0) {
2091 return max_total_wal_size;
2092 }
2093 return 4 * max_total_in_memory_state_.load(std::memory_order_acquire);
2094}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetMergeOperands()

Status ROCKSDB_NAMESPACE::DBImpl::GetMergeOperands ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
PinnableSlice * merge_operands,
GetMergeOperandsOptions * get_merge_operands_options,
int * number_of_operands )
inlineoverridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.h 파일의 255 번째 라인에서 정의되었습니다.

259 {
260 GetImplOptions get_impl_options;
261 get_impl_options.column_family = column_family;
262 get_impl_options.merge_operands = merge_operands;
263 get_impl_options.get_merge_operands_options = get_merge_operands_options;
264 get_impl_options.number_of_operands = number_of_operands;
265 get_impl_options.get_value = false;
266 return GetImpl(options, key, get_impl_options);
267 }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ GetName()

const std::string & ROCKSDB_NAMESPACE::DBImpl::GetName ( ) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4466 번째 라인에서 정의되었습니다.

4466{ return dbname_; }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetObsoleteSstFilesSize()

uint64_t ROCKSDB_NAMESPACE::DBImpl::GetObsoleteSstFilesSize ( )

db_impl_files.cc 파일의 41 번째 라인에서 정의되었습니다.

41 {
42 mutex_.AssertHeld();
43 return versions_->GetObsoleteSstFilesSize();
44}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetOpenWalSizes()

Status ROCKSDB_NAMESPACE::DBImpl::GetOpenWalSizes ( std::map< uint64_t, uint64_t > & number_to_size)

db_impl.cc 파일의 1585 번째 라인에서 정의되었습니다.

1585 {
1586 assert(number_to_size.empty());
1587 InstrumentedMutexLock l(&log_write_mutex_);
1588 for (auto& log : logs_) {
1589 auto* open_file = log.writer->file();
1590 if (open_file) {
1591 number_to_size[log.number] = open_file->GetFlushedSize();
1592 }
1593 }
1594 return Status::OK();
1595}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetOptions() [1/2]

virtual Options ROCKSDB_NAMESPACE::DB::GetOptions ( ) const
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1644 번째 라인에서 정의되었습니다.

1644 {
1646 }
Options GetOptions(ColumnFamilyHandle *column_family) const override
Definition db_impl.cc:4495

◆ GetOptions() [2/2]

Options ROCKSDB_NAMESPACE::DBImpl::GetOptions ( ColumnFamilyHandle * column_family) const
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4495 번째 라인에서 정의되었습니다.

4495 {
4496 InstrumentedMutexLock l(&mutex_);
4497 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
4498 return Options(BuildDBOptions(immutable_db_options_, mutable_db_options_),
4499 cfh->cfd()->GetLatestCFOptions());
4500}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetPropertiesOfAllTables() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::GetPropertiesOfAllTables ( ColumnFamilyHandle * column_family,
TablePropertiesCollection * props )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4401 번째 라인에서 정의되었습니다.

4402 {
4403 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
4404 auto cfd = cfh->cfd();
4405
4406 // Increment the ref count
4407 mutex_.Lock();
4408 auto version = cfd->current();
4409 version->Ref();
4410 mutex_.Unlock();
4411
4412 // TODO: plumb Env::IOActivity, Env::IOPriority
4413 const ReadOptions read_options;
4414 auto s = version->GetPropertiesOfAllTables(read_options, props);
4415
4416 // Decrement the ref count
4417 mutex_.Lock();
4418 version->Unref();
4419 mutex_.Unlock();
4420
4421 return s;
4422}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetPropertiesOfAllTables() [2/2]

virtual Status ROCKSDB_NAMESPACE::DB::GetPropertiesOfAllTables ( TablePropertiesCollection * props)
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 2009 번째 라인에서 정의되었습니다.

2009 {
2011 }
Status GetPropertiesOfAllTables(ColumnFamilyHandle *column_family, TablePropertiesCollection *props) override
Definition db_impl.cc:4401

◆ GetPropertiesOfTablesInRange()

Status ROCKSDB_NAMESPACE::DBImpl::GetPropertiesOfTablesInRange ( ColumnFamilyHandle * column_family,
const Range * range,
std::size_t n,
TablePropertiesCollection * props )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4424 번째 라인에서 정의되었습니다.

4426 {
4427 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
4428 auto cfd = cfh->cfd();
4429
4430 // Increment the ref count
4431 mutex_.Lock();
4432 auto version = cfd->current();
4433 version->Ref();
4434 mutex_.Unlock();
4435
4436 // TODO: plumb Env::IOActivity, Env::IOPriority
4437 const ReadOptions read_options;
4438 const Comparator* const ucmp = cfd->user_comparator();
4439 assert(ucmp);
4440 size_t ts_sz = ucmp->timestamp_size();
4441
4442 autovector<UserKeyRange> ukey_ranges;
4443 std::vector<std::string> keys;
4444 ukey_ranges.reserve(n);
4445 keys.reserve(2 * n);
4446 // Add timestamp if needed
4447 for (size_t i = 0; i < n; i++) {
4448 auto [start, limit] = MaybeAddTimestampsToRange(
4449 &range[i].start, &range[i].limit, ts_sz, &keys.emplace_back(),
4450 &keys.emplace_back(), /*exclusive_end=*/false);
4451 assert(start.has_value());
4452 assert(limit.has_value());
4453 ukey_ranges.emplace_back(start.value(), limit.value());
4454 }
4455 auto s =
4456 version->GetPropertiesOfTablesInRange(read_options, ukey_ranges, props);
4457
4458 // Decrement the ref count
4459 mutex_.Lock();
4460 version->Unref();
4461 mutex_.Unlock();
4462
4463 return s;
4464}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetProperty() [1/2]

bool ROCKSDB_NAMESPACE::DBImpl::GetProperty ( ColumnFamilyHandle * column_family,
const Slice & property,
std::string * value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4507 번째 라인에서 정의되었습니다.

4508 {
4509 const DBPropertyInfo* property_info = GetPropertyInfo(property);
4510 value->clear();
4511 auto cfd =
4512 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
4513 if (property_info == nullptr) {
4514 return false;
4515 } else if (property_info->handle_int) {
4516 uint64_t int_value;
4517 bool ret_value =
4518 GetIntPropertyInternal(cfd, *property_info, false, &int_value);
4519 if (ret_value) {
4520 *value = std::to_string(int_value);
4521 }
4522 return ret_value;
4523 } else if (property_info->handle_string) {
4524 if (property_info->need_out_of_mutex) {
4525 return cfd->internal_stats()->GetStringProperty(*property_info, property,
4526 value);
4527 } else {
4528 InstrumentedMutexLock l(&mutex_);
4529 return cfd->internal_stats()->GetStringProperty(*property_info, property,
4530 value);
4531 }
4532 } else if (property_info->handle_string_dbimpl) {
4533 if (property_info->need_out_of_mutex) {
4534 return (this->*(property_info->handle_string_dbimpl))(value);
4535 } else {
4536 InstrumentedMutexLock l(&mutex_);
4537 return (this->*(property_info->handle_string_dbimpl))(value);
4538 }
4539 }
4540 // Shouldn't reach here since exactly one of handle_string and handle_int
4541 // should be non-nullptr.
4542 assert(false);
4543 return false;
4544}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetProperty() [2/2]

virtual bool ROCKSDB_NAMESPACE::DB::GetProperty ( const Slice & property,
std::string * value )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1342 번째 라인에서 정의되었습니다.

1342 {
1343 return GetProperty(DefaultColumnFamily(), property, value);
1344 }
bool GetProperty(ColumnFamilyHandle *column_family, const Slice &property, std::string *value) override
Definition db_impl.cc:4507

◆ GetPropertyHandleOptionsStatistics()

bool ROCKSDB_NAMESPACE::DBImpl::GetPropertyHandleOptionsStatistics ( std::string * value)
private

db_impl.cc 파일의 4612 번째 라인에서 정의되었습니다.

4612 {
4613 assert(value != nullptr);
4614 Statistics* statistics = immutable_db_options_.stats;
4615 if (!statistics) {
4616 return false;
4617 }
4618 *value = statistics->ToString();
4619 return true;
4620}
virtual std::string ToString() const
Definition statistics.h:771
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetRecoveredTransaction()

RecoveredTransaction * ROCKSDB_NAMESPACE::DBImpl::GetRecoveredTransaction ( const std::string & name)
inline

db_impl.h 파일의 1008 번째 라인에서 정의되었습니다.

1008 {
1009 auto it = recovered_transactions_.find(name);
1010 if (it == recovered_transactions_.end()) {
1011 return nullptr;
1012 } else {
1013 return it->second;
1014 }
1015 }

◆ GetSnapshot()

const Snapshot * ROCKSDB_NAMESPACE::DBImpl::GetSnapshot ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4129 번째 라인에서 정의되었습니다.

4129{ return GetSnapshotImpl(false); }
SnapshotImpl * GetSnapshotImpl(bool is_write_conflict_boundary, bool lock=true)
Definition db_impl.cc:4177
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetSnapshotContext()

void ROCKSDB_NAMESPACE::DBImpl::GetSnapshotContext ( JobContext * job_context,
std::vector< SequenceNumber > * snapshot_seqs,
SequenceNumber * earliest_write_conflict_snapshot,
SnapshotChecker ** snapshot_checker )

db_impl_compaction_flush.cc 파일의 4362 번째 라인에서 정의되었습니다.

4365 {
4366 mutex_.AssertHeld();
4367 assert(job_context != nullptr);
4368 assert(snapshot_seqs != nullptr);
4369 assert(earliest_write_conflict_snapshot != nullptr);
4370 assert(snapshot_checker_ptr != nullptr);
4371
4372 *snapshot_checker_ptr = snapshot_checker_.get();
4373 if (use_custom_gc_ && *snapshot_checker_ptr == nullptr) {
4374 *snapshot_checker_ptr = DisableGCSnapshotChecker::Instance();
4375 }
4376 if (*snapshot_checker_ptr != nullptr) {
4377 // If snapshot_checker is used, that means the flush/compaction may
4378 // contain values not visible to snapshot taken after
4379 // flush/compaction job starts. Take a snapshot and it will appear
4380 // in snapshot_seqs and force compaction iterator to consider such
4381 // snapshots.
4382 const Snapshot* job_snapshot =
4383 GetSnapshotImpl(false /*write_conflict_boundary*/, false /*lock*/);
4384 job_context->job_snapshot.reset(new ManagedSnapshot(this, job_snapshot));
4385 }
4386 *snapshot_seqs = snapshots_.GetAll(earliest_write_conflict_snapshot);
4387}
std::unique_ptr< SnapshotChecker > snapshot_checker_
Definition db_impl.h:2951
std::vector< SequenceNumber > GetAll(SequenceNumber *oldest_write_conflict_snapshot=nullptr, const SequenceNumber &max_seq=kMaxSequenceNumber) const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetSnapshotForWriteConflictBoundary()

const Snapshot * ROCKSDB_NAMESPACE::DBImpl::GetSnapshotForWriteConflictBoundary ( )

db_impl.cc 파일의 4131 번째 라인에서 정의되었습니다.

4131 {
4132 return GetSnapshotImpl(true);
4133}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetSnapshotImpl()

SnapshotImpl * ROCKSDB_NAMESPACE::DBImpl::GetSnapshotImpl ( bool is_write_conflict_boundary,
bool lock = true )
private

db_impl.cc 파일의 4177 번째 라인에서 정의되었습니다.

4178 {
4179 int64_t unix_time = 0;
4181 .PermitUncheckedError(); // Ignore error
4182 SnapshotImpl* s = new SnapshotImpl;
4183
4184 if (lock) {
4185 mutex_.Lock();
4186 } else {
4187 mutex_.AssertHeld();
4188 }
4189 // returns null if the underlying memtable does not support snapshot.
4190 if (!is_snapshot_supported_) {
4191 if (lock) {
4192 mutex_.Unlock();
4193 }
4194 delete s;
4195 return nullptr;
4196 }
4197 auto snapshot_seq = GetLastPublishedSequence();
4198 SnapshotImpl* snapshot =
4199 snapshots_.New(s, snapshot_seq, unix_time, is_write_conflict_boundary);
4200 if (lock) {
4201 mutex_.Unlock();
4202 }
4203 return snapshot;
4204}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetSortedWalFiles()

Status ROCKSDB_NAMESPACE::DBImpl::GetSortedWalFiles ( VectorWalPtr & files)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_filesnapshot.cc 파일의 95 번째 라인에서 정의되었습니다.

95 {
96 return GetSortedWalFilesImpl(files,
97 /*need_seqnos*/ true);
98}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetSortedWalFilesImpl()

Status ROCKSDB_NAMESPACE::DBImpl::GetSortedWalFilesImpl ( VectorWalPtr & files,
bool need_seqnos )

db_filesnapshot.cc 파일의 100 번째 라인에서 정의되었습니다.

100 {
101 // Record tracked WALs as a (minimum) cross-check for directory scan
102 std::vector<uint64_t> required_by_manifest;
103
104 // If caller disabled deletions, this function should return files that are
105 // guaranteed not to be deleted until deletions are re-enabled. We need to
106 // wait for pending purges to finish since WalManager doesn't know which
107 // files are going to be purged. Additional purges won't be scheduled as
108 // long as deletions are disabled (so the below loop must terminate).
109 // Also note that we disable deletions anyway to avoid the case where a
110 // file is deleted in the middle of the scan, causing IO error.
111 Status deletions_disabled = DisableFileDeletions();
112 {
113 InstrumentedMutexLock l(&mutex_);
114 while (pending_purge_obsolete_files_ > 0 || bg_purge_scheduled_ > 0) {
115 bg_cv_.Wait();
116 }
117
118 // Record tracked WALs as a (minimum) cross-check for directory scan
119 const auto& manifest_wals = versions_->GetWalSet().GetWals();
120 required_by_manifest.reserve(manifest_wals.size());
121 for (const auto& wal : manifest_wals) {
122 required_by_manifest.push_back(wal.first);
123 }
124 }
125
126 // NOTE: need to include archived WALs because needed WALs might have been
127 // archived since getting required_by_manifest set
128 Status s = wal_manager_.GetSortedWalFiles(files, need_seqnos,
129 /*include_archived*/ true);
130
131 // DisableFileDeletions / EnableFileDeletions not supported in read-only DB
132 if (deletions_disabled.ok()) {
133 Status s2 = EnableFileDeletions();
134 assert(s2.ok());
135 s2.PermitUncheckedError();
136 } else {
137 assert(deletions_disabled.IsNotSupported());
138 }
139
140 if (s.ok()) {
141 // Verify includes those required by manifest (one sorted list is superset
142 // of the other)
143 auto required = required_by_manifest.begin();
144 auto included = files.begin();
145
146 while (required != required_by_manifest.end()) {
147 if (included == files.end() || *required < (*included)->LogNumber()) {
148 // FAIL - did not find
149 return Status::Corruption(
150 "WAL file " + std::to_string(*required) +
151 " required by manifest but not in directory list");
152 }
153 if (*required == (*included)->LogNumber()) {
154 ++required;
155 ++included;
156 } else {
157 assert(*required > (*included)->LogNumber());
158 ++included;
159 }
160 }
161 }
162
163 if (s.ok()) {
164 size_t wal_count = files.size();
166 "Number of WAL files %" ROCKSDB_PRIszt " (%" ROCKSDB_PRIszt
167 " required by manifest)",
168 wal_count, required_by_manifest.size());
169#ifndef NDEBUG
170 std::ostringstream wal_names;
171 for (const auto& wal : files) {
172 wal_names << wal->PathName() << " ";
173 }
174
175 std::ostringstream wal_required_by_manifest_names;
176 for (const auto& wal : required_by_manifest) {
177 wal_required_by_manifest_names << wal << ".log ";
178 }
179
181 "Log files : %s .Log files required by manifest: %s.",
182 wal_names.str().c_str(),
183 wal_required_by_manifest_names.str().c_str());
184#endif // NDEBUG
185 }
186 return s;
187}
Status DisableFileDeletions() override
Status EnableFileDeletions() override
#define ROCKSDB_PRIszt
Definition port_posix.h:22
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetStatsHistory()

Status ROCKSDB_NAMESPACE::DBImpl::GetStatsHistory ( uint64_t start_time,
uint64_t end_time,
std::unique_ptr< StatsHistoryIterator > * stats_iterator )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 1136 번째 라인에서 정의되었습니다.

1138 {
1139 if (!stats_iterator) {
1140 return Status::InvalidArgument("stats_iterator not preallocated.");
1141 }
1143 stats_iterator->reset(
1144 new PersistentStatsHistoryIterator(start_time, end_time, this));
1145 } else {
1146 stats_iterator->reset(
1147 new InMemoryStatsHistoryIterator(start_time, end_time, this));
1148 }
1149 return (*stats_iterator)->status();
1150}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetSystemClock()

SystemClock * ROCKSDB_NAMESPACE::DBImpl::GetSystemClock ( ) const

db_impl.cc 파일의 4479 번째 라인에서 정의되었습니다.

4479 {
4481}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetTaskTag() [1/2]

void * ROCKSDB_NAMESPACE::DBImpl::GetTaskTag ( TaskType type)
inlineprivate

db_impl.h 파일의 2193 번째 라인에서 정의되었습니다.

2193 {
2194 return GetTaskTag(static_cast<uint8_t>(type));
2195 }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetTaskTag() [2/2]

void * ROCKSDB_NAMESPACE::DBImpl::GetTaskTag ( uint8_t type)
inlineprivate

db_impl.h 파일의 2197 번째 라인에서 정의되었습니다.

2197 {
2198 return static_cast<uint8_t*>(static_cast<void*>(this)) + type;
2199 }

◆ GetTimestampedSnapshot()

std::shared_ptr< const SnapshotImpl > ROCKSDB_NAMESPACE::DBImpl::GetTimestampedSnapshot ( uint64_t ts) const

db_impl.cc 파일의 4143 번째 라인에서 정의되었습니다.

4144 {
4145 InstrumentedMutexLock lock_guard(&mutex_);
4147}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetTimestampedSnapshots()

Status ROCKSDB_NAMESPACE::DBImpl::GetTimestampedSnapshots ( uint64_t ts_lb,
uint64_t ts_ub,
std::vector< std::shared_ptr< const Snapshot > > & timestamped_snapshots ) const

db_impl.cc 파일의 4164 번째 라인에서 정의되었습니다.

4166 {
4167 if (ts_lb >= ts_ub) {
4168 return Status::InvalidArgument(
4169 "timestamp lower bound must be smaller than upper bound");
4170 }
4171 timestamped_snapshots.clear();
4172 InstrumentedMutexLock lock_guard(&mutex_);
4173 timestamped_snapshots_.GetSnapshots(ts_lb, ts_ub, timestamped_snapshots);
4174 return Status::OK();
4175}
void GetSnapshots(uint64_t ts_lb, uint64_t ts_ub, std::vector< std::shared_ptr< const Snapshot > > &snapshots) const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetUpdatesSince()

Status ROCKSDB_NAMESPACE::DBImpl::GetUpdatesSince ( SequenceNumber seq_number,
std::unique_ptr< TransactionLogIterator > * iter,
const TransactionLogIterator::ReadOptions & read_options = TransactionLogIterator::ReadOptions() )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4866 번째 라인에서 정의되었습니다.

4868 {
4869 RecordTick(stats_, GET_UPDATES_SINCE_CALLS);
4870 if (seq_per_batch_) {
4871 return Status::NotSupported(
4872 "This API is not yet compatible with write-prepared/write-unprepared "
4873 "transactions");
4874 }
4875 if (seq > versions_->LastSequence()) {
4876 return Status::NotFound("Requested sequence not yet written in the db");
4877 }
4878 return wal_manager_.GetUpdatesSince(seq, iter, read_options, versions_.get());
4879}
Status GetUpdatesSince(SequenceNumber seq_number, std::unique_ptr< TransactionLogIterator > *iter, const TransactionLogIterator::ReadOptions &read_options, VersionSet *version_set)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetVersionSet()

VersionSet * ROCKSDB_NAMESPACE::DBImpl::GetVersionSet ( ) const
inline

db_impl.h 파일의 1105 번째 라인에서 정의되었습니다.

1105{ return versions_.get(); }

◆ GetWalPreallocateBlockSize()

size_t ROCKSDB_NAMESPACE::DBImpl::GetWalPreallocateBlockSize ( uint64_t write_buffer_size) const
private

db_impl_write.cc 파일의 2639 번째 라인에서 정의되었습니다.

2639 {
2640 mutex_.AssertHeld();
2641 size_t bsize =
2642 static_cast<size_t>(write_buffer_size / 10 + write_buffer_size);
2643 // Some users might set very high write_buffer_size and rely on
2644 // max_total_wal_size or other parameters to control the WAL size.
2646 bsize = std::min<size_t>(
2647 bsize, static_cast<size_t>(mutable_db_options_.max_total_wal_size));
2648 }
2650 bsize = std::min<size_t>(bsize, immutable_db_options_.db_write_buffer_size);
2651 }
2654 bsize = std::min<size_t>(
2655 bsize, immutable_db_options_.write_buffer_manager->buffer_size());
2656 }
2657
2658 return bsize;
2659}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HandleWriteBufferManagerFlush()

Status ROCKSDB_NAMESPACE::DBImpl::HandleWriteBufferManagerFlush ( WriteContext * write_context)
private

db_impl_write.cc 파일의 1995 번째 라인에서 정의되었습니다.

1995 {
1996 mutex_.AssertHeld();
1997 assert(write_context != nullptr);
1998 Status status;
1999
2000 // Before a new memtable is added in SwitchMemtable(),
2001 // write_buffer_manager_->ShouldFlush() will keep returning true. If another
2002 // thread is writing to another DB with the same write buffer, they may also
2003 // be flushed. We may end up with flushing much more DBs than needed. It's
2004 // suboptimal but still correct.
2005 // no need to refcount because drop is happening in write thread, so can't
2006 // happen while we're in the write thread
2007 autovector<ColumnFamilyData*> cfds;
2010 } else {
2011 ColumnFamilyData* cfd_picked = nullptr;
2012 SequenceNumber seq_num_for_cf_picked = kMaxSequenceNumber;
2013
2014 for (auto cfd : *versions_->GetColumnFamilySet()) {
2015 if (cfd->IsDropped()) {
2016 continue;
2017 }
2018 if (!cfd->mem()->IsEmpty() && !cfd->imm()->IsFlushPendingOrRunning()) {
2019 // We only consider flush on CFs with bytes in the mutable memtable,
2020 // and no immutable memtables for which flush has yet to finish. If
2021 // we triggered flush on CFs already trying to flush, we would risk
2022 // creating too many immutable memtables leading to write stalls.
2023 uint64_t seq = cfd->mem()->GetCreationSeq();
2024 if (cfd_picked == nullptr || seq < seq_num_for_cf_picked) {
2025 cfd_picked = cfd;
2026 seq_num_for_cf_picked = seq;
2027 }
2028 }
2029 }
2030 if (cfd_picked != nullptr) {
2031 cfds.push_back(cfd_picked);
2032 }
2033 MaybeFlushStatsCF(&cfds);
2034 }
2035 if (!cfds.empty()) {
2038 "Flushing triggered to alleviate write buffer memory usage. Write "
2039 "buffer is using %" ROCKSDB_PRIszt
2040 " bytes out of a total of %" ROCKSDB_PRIszt ".",
2043 }
2044
2045 WriteThread::Writer nonmem_w;
2046 if (two_write_queues_) {
2047 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
2048 }
2049 for (const auto cfd : cfds) {
2050 if (cfd->mem()->IsEmpty()) {
2051 continue;
2052 }
2053 cfd->Ref();
2054 status = SwitchMemtable(cfd, write_context);
2055 cfd->UnrefAndTryDelete();
2056 if (!status.ok()) {
2057 break;
2058 }
2059 }
2060 if (two_write_queues_) {
2062 }
2063
2064 if (status.ok()) {
2067 }
2068 for (const auto cfd : cfds) {
2069 cfd->imm()->FlushRequested();
2071 FlushRequest flush_req;
2072 GenerateFlushRequest({cfd}, FlushReason::kWriteBufferManager,
2073 &flush_req);
2074 EnqueuePendingFlush(flush_req);
2075 }
2076 }
2078 FlushRequest flush_req;
2079 GenerateFlushRequest(cfds, FlushReason::kWriteBufferManager, &flush_req);
2080 EnqueuePendingFlush(flush_req);
2081 }
2083 }
2084 return status;
2085}
void MaybeFlushStatsCF(autovector< ColumnFamilyData * > *cfds)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HasExclusiveManualCompaction()

bool ROCKSDB_NAMESPACE::DBImpl::HasExclusiveManualCompaction ( )
private

db_impl_compaction_flush.cc 파일의 4161 번째 라인에서 정의되었습니다.

4161 {
4162 // Remove from priority queue
4163 std::deque<ManualCompactionState*>::iterator it =
4165 while (it != manual_compaction_dequeue_.end()) {
4166 if ((*it)->exclusive) {
4167 return true;
4168 }
4169 ++it;
4170 }
4171 return false;
4172}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HasPendingManualCompaction()

bool ROCKSDB_NAMESPACE::DBImpl::HasPendingManualCompaction ( )
private

db_impl_compaction_flush.cc 파일의 4096 번째 라인에서 정의되었습니다.

4096 {
4097 return (!manual_compaction_dequeue_.empty());
4098}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HaveManualCompaction()

bool ROCKSDB_NAMESPACE::DBImpl::HaveManualCompaction ( ColumnFamilyData * cfd)
private

db_impl_compaction_flush.cc 파일의 4143 번째 라인에서 정의되었습니다.

4143 {
4144 // Remove from priority queue
4145 std::deque<ManualCompactionState*>::iterator it =
4147 while (it != manual_compaction_dequeue_.end()) {
4148 if ((*it)->exclusive) {
4149 return true;
4150 }
4151 if ((cfd == (*it)->cfd) && (!((*it)->in_progress || (*it)->done))) {
4152 // Allow automatic compaction if manual compaction is
4153 // in progress
4154 return true;
4155 }
4156 ++it;
4157 }
4158 return false;
4159}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ immutable_db_options()

const ImmutableDBOptions & ROCKSDB_NAMESPACE::DBImpl::immutable_db_options ( ) const
inline

db_impl.h 파일의 892 번째 라인에서 정의되었습니다.

892 {
894 }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IncreaseFullHistoryTsLow()

Status ROCKSDB_NAMESPACE::DBImpl::IncreaseFullHistoryTsLow ( ColumnFamilyHandle * column_family,
std::string ts_low )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 995 번째 라인에서 정의되었습니다.

996 {
997 ColumnFamilyData* cfd = nullptr;
998 if (column_family == nullptr) {
999 cfd = default_cf_handle_->cfd();
1000 } else {
1001 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1002 assert(cfh != nullptr);
1003 cfd = cfh->cfd();
1004 }
1005 assert(cfd != nullptr && cfd->user_comparator() != nullptr);
1006 if (cfd->user_comparator()->timestamp_size() == 0) {
1007 return Status::InvalidArgument(
1008 "Timestamp is not enabled in this column family");
1009 }
1010 if (cfd->user_comparator()->timestamp_size() != ts_low.size()) {
1011 return Status::InvalidArgument("ts_low size mismatch");
1012 }
1013 return IncreaseFullHistoryTsLowImpl(cfd, ts_low);
1014}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IncreaseFullHistoryTsLowImpl()

Status ROCKSDB_NAMESPACE::DBImpl::IncreaseFullHistoryTsLowImpl ( ColumnFamilyData * cfd,
std::string ts_low )
private

db_impl_compaction_flush.cc 파일의 1016 번째 라인에서 정의되었습니다.

1017 {
1018 VersionEdit edit;
1019 edit.SetColumnFamily(cfd->GetID());
1020 edit.SetFullHistoryTsLow(ts_low);
1021
1022 // TODO: plumb Env::IOActivity, Env::IOPriority
1023 const ReadOptions read_options;
1024 const WriteOptions write_options;
1025
1026 TEST_SYNC_POINT_CALLBACK("DBImpl::IncreaseFullHistoryTsLowImpl:BeforeEdit",
1027 &edit);
1028
1029 InstrumentedMutexLock l(&mutex_);
1030 std::string current_ts_low = cfd->GetFullHistoryTsLow();
1031 const Comparator* ucmp = cfd->user_comparator();
1032 assert(ucmp->timestamp_size() == ts_low.size() && !ts_low.empty());
1033 if (!current_ts_low.empty() &&
1034 ucmp->CompareTimestamp(ts_low, current_ts_low) < 0) {
1035 std::stringstream oss;
1036 oss << "Current full_history_ts_low: "
1037 << ucmp->TimestampToString(current_ts_low)
1038 << " is higher than provided ts: " << ucmp->TimestampToString(ts_low)
1039 << std::endl;
1040 return Status::InvalidArgument(oss.str());
1041 }
1042
1043 Status s = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
1044 read_options, write_options, &edit, &mutex_,
1046 if (!s.ok()) {
1047 return s;
1048 }
1049 current_ts_low = cfd->GetFullHistoryTsLow();
1050 if (!current_ts_low.empty() &&
1051 ucmp->CompareTimestamp(current_ts_low, ts_low) > 0) {
1052 std::stringstream oss;
1053 oss << "full_history_ts_low: " << Slice(current_ts_low).ToString(true)
1054 << " is set to be higher than the requested "
1055 "timestamp: "
1056 << Slice(ts_low).ToString(true) << std::endl;
1057 return Status::TryAgain(oss.str());
1058 }
1059 return Status::OK();
1060}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IngestExternalFile() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::IngestExternalFile ( ColumnFamilyHandle * column_family,
const std::vector< std::string > & external_files,
const IngestExternalFileOptions & ingestion_options )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 5887 번째 라인에서 정의되었습니다.

5890 {
5891 IngestExternalFileArg arg;
5892 arg.column_family = column_family;
5893 arg.external_files = external_files;
5894 arg.options = ingestion_options;
5895 return IngestExternalFiles({arg});
5896}
Status IngestExternalFiles(const std::vector< IngestExternalFileArg > &args) override
Definition db_impl.cc:5898
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IngestExternalFile() [2/2]

virtual Status ROCKSDB_NAMESPACE::DB::IngestExternalFile ( const std::vector< std::string > & external_files,
const IngestExternalFileOptions & options )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 1902 번째 라인에서 정의되었습니다.

1904 {
1905 return IngestExternalFile(DefaultColumnFamily(), external_files, options);
1906 }
Status IngestExternalFile(ColumnFamilyHandle *column_family, const std::vector< std::string > &external_files, const IngestExternalFileOptions &ingestion_options) override
Definition db_impl.cc:5887

◆ IngestExternalFiles()

Status ROCKSDB_NAMESPACE::DBImpl::IngestExternalFiles ( const std::vector< IngestExternalFileArg > & args)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 5898 번째 라인에서 정의되었습니다.

5899 {
5900 // TODO: plumb Env::IOActivity, Env::IOPriority
5901 const WriteOptions write_options;
5902
5903 if (args.empty()) {
5904 return Status::InvalidArgument("ingestion arg list is empty");
5905 }
5906 {
5907 std::unordered_set<ColumnFamilyHandle*> unique_cfhs;
5908 for (const auto& arg : args) {
5909 if (arg.column_family == nullptr) {
5910 return Status::InvalidArgument("column family handle is null");
5911 } else if (unique_cfhs.count(arg.column_family) > 0) {
5912 return Status::InvalidArgument(
5913 "ingestion args have duplicate column families");
5914 }
5915 unique_cfhs.insert(arg.column_family);
5916 }
5917 }
5918 // Ingest multiple external SST files atomically.
5919 const size_t num_cfs = args.size();
5920 for (size_t i = 0; i != num_cfs; ++i) {
5921 if (args[i].external_files.empty()) {
5922 std::string err_msg =
5923 "external_files[" + std::to_string(i) + "] is empty";
5924 return Status::InvalidArgument(err_msg);
5925 }
5926 if (i && args[i].options.fill_cache != args[i - 1].options.fill_cache) {
5927 return Status::InvalidArgument(
5928 "fill_cache should be the same across ingestion options.");
5929 }
5930 }
5931 for (const auto& arg : args) {
5932 const IngestExternalFileOptions& ingest_opts = arg.options;
5933 if (ingest_opts.ingest_behind) {
5935 return Status::InvalidArgument(
5936 "can't ingest_behind file in DB with allow_ingest_behind=false");
5937 }
5938 auto ucmp = arg.column_family->GetComparator();
5939 assert(ucmp);
5940 if (ucmp->timestamp_size() > 0) {
5941 return Status::NotSupported(
5942 "Column family with user-defined "
5943 "timestamps enabled doesn't support ingest behind.");
5944 }
5945 }
5946 if (ingest_opts.allow_db_generated_files) {
5947 if (ingest_opts.write_global_seqno) {
5948 return Status::NotSupported(
5949 "write_global_seqno is deprecated and does not work with "
5950 "allow_db_generated_files.");
5951 }
5952 }
5953 if (ingest_opts.move_files && ingest_opts.link_files) {
5954 return Status::InvalidArgument(
5955 "`move_files` and `link_files` can not both be true.");
5956 }
5957 }
5958
5959 // TODO (yanqin) maybe handle the case in which column_families have
5960 // duplicates
5961 std::unique_ptr<std::list<uint64_t>::iterator> pending_output_elem;
5962 size_t total = 0;
5963 for (const auto& arg : args) {
5964 total += arg.external_files.size();
5965 }
5966 uint64_t next_file_number = 0;
5967 Status status = ReserveFileNumbersBeforeIngestion(
5968 static_cast<ColumnFamilyHandleImpl*>(args[0].column_family)->cfd(), total,
5969 pending_output_elem, &next_file_number);
5970 if (!status.ok()) {
5971 InstrumentedMutexLock l(&mutex_);
5972 ReleaseFileNumberFromPendingOutputs(pending_output_elem);
5973 return status;
5974 }
5975
5976 std::vector<ExternalSstFileIngestionJob> ingestion_jobs;
5977 for (const auto& arg : args) {
5978 auto* cfd = static_cast<ColumnFamilyHandleImpl*>(arg.column_family)->cfd();
5979 ingestion_jobs.emplace_back(versions_.get(), cfd, immutable_db_options_,
5980 mutable_db_options_, file_options_, &snapshots_,
5981 arg.options, &directories_, &event_logger_,
5982 io_tracer_);
5983 }
5984
5985 // TODO(yanqin) maybe make jobs run in parallel
5986 uint64_t start_file_number = next_file_number;
5987 for (size_t i = 1; i != num_cfs; ++i) {
5988 start_file_number += args[i - 1].external_files.size();
5989 SuperVersion* super_version =
5990 ingestion_jobs[i].GetColumnFamilyData()->GetReferencedSuperVersion(
5991 this);
5992 Status es = ingestion_jobs[i].Prepare(
5993 args[i].external_files, args[i].files_checksums,
5994 args[i].files_checksum_func_names, args[i].file_temperature,
5995 start_file_number, super_version);
5996 // capture first error only
5997 if (!es.ok() && status.ok()) {
5998 status = es;
5999 }
6000 CleanupSuperVersion(super_version);
6001 }
6002 TEST_SYNC_POINT("DBImpl::IngestExternalFiles:BeforeLastJobPrepare:0");
6003 TEST_SYNC_POINT("DBImpl::IngestExternalFiles:BeforeLastJobPrepare:1");
6004 {
6005 SuperVersion* super_version =
6006 ingestion_jobs[0].GetColumnFamilyData()->GetReferencedSuperVersion(
6007 this);
6008 Status es = ingestion_jobs[0].Prepare(
6009 args[0].external_files, args[0].files_checksums,
6010 args[0].files_checksum_func_names, args[0].file_temperature,
6011 next_file_number, super_version);
6012 if (!es.ok()) {
6013 status = es;
6014 }
6015 CleanupSuperVersion(super_version);
6016 }
6017 if (!status.ok()) {
6018 for (size_t i = 0; i != num_cfs; ++i) {
6019 ingestion_jobs[i].Cleanup(status);
6020 }
6021 InstrumentedMutexLock l(&mutex_);
6022 ReleaseFileNumberFromPendingOutputs(pending_output_elem);
6023 return status;
6024 }
6025
6026 std::vector<SuperVersionContext> sv_ctxs;
6027 for (size_t i = 0; i != num_cfs; ++i) {
6028 sv_ctxs.emplace_back(true /* create_superversion */);
6029 }
6030 TEST_SYNC_POINT("DBImpl::IngestExternalFiles:BeforeJobsRun:0");
6031 TEST_SYNC_POINT("DBImpl::IngestExternalFiles:BeforeJobsRun:1");
6032 TEST_SYNC_POINT("DBImpl::AddFile:Start");
6033 {
6034 InstrumentedMutexLock l(&mutex_);
6035 TEST_SYNC_POINT("DBImpl::AddFile:MutexLock");
6036
6037 // Stop writes to the DB by entering both write threads
6038 WriteThread::Writer w;
6039 write_thread_.EnterUnbatched(&w, &mutex_);
6040 WriteThread::Writer nonmem_w;
6041 if (two_write_queues_) {
6042 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
6043 }
6044
6045 // When unordered_write is enabled, the keys are writing to memtable in an
6046 // unordered way. If the ingestion job checks memtable key range before the
6047 // key landing in memtable, the ingestion job may skip the necessary
6048 // memtable flush.
6049 // So wait here to ensure there is no pending write to memtable.
6051
6052 num_running_ingest_file_ += static_cast<int>(num_cfs);
6053 TEST_SYNC_POINT("DBImpl::IngestExternalFile:AfterIncIngestFileCounter");
6054
6055 bool at_least_one_cf_need_flush = false;
6056 std::vector<bool> need_flush(num_cfs, false);
6057 for (size_t i = 0; i != num_cfs; ++i) {
6058 auto* cfd = ingestion_jobs[i].GetColumnFamilyData();
6059 if (cfd->IsDropped()) {
6060 // TODO (yanqin) investigate whether we should abort ingestion or
6061 // proceed with other non-dropped column families.
6062 status = Status::InvalidArgument(
6063 "cannot ingest an external file into a dropped CF");
6064 break;
6065 }
6066 bool tmp = false;
6067 status = ingestion_jobs[i].NeedsFlush(&tmp, cfd->GetSuperVersion());
6068 need_flush[i] = tmp;
6069 at_least_one_cf_need_flush = (at_least_one_cf_need_flush || tmp);
6070 if (!status.ok()) {
6071 break;
6072 }
6073 }
6074 TEST_SYNC_POINT_CALLBACK("DBImpl::IngestExternalFile:NeedFlush",
6075 &at_least_one_cf_need_flush);
6076
6077 if (status.ok() && at_least_one_cf_need_flush) {
6078 FlushOptions flush_opts;
6079 flush_opts.allow_write_stall = true;
6081 mutex_.Unlock();
6082 status = AtomicFlushMemTables(
6083 flush_opts, FlushReason::kExternalFileIngestion,
6084 {} /* provided_candidate_cfds */, true /* entered_write_thread */);
6085 mutex_.Lock();
6086 } else {
6087 for (size_t i = 0; i != num_cfs; ++i) {
6088 if (need_flush[i]) {
6089 mutex_.Unlock();
6090 status =
6091 FlushMemTable(ingestion_jobs[i].GetColumnFamilyData(),
6092 flush_opts, FlushReason::kExternalFileIngestion,
6093 true /* entered_write_thread */);
6094 mutex_.Lock();
6095 if (!status.ok()) {
6096 break;
6097 }
6098 }
6099 }
6100 }
6101 if (status.ok()) {
6102 for (size_t i = 0; i != num_cfs; ++i) {
6103 if (immutable_db_options_.atomic_flush || need_flush[i]) {
6104 ingestion_jobs[i].SetFlushedBeforeRun();
6105 }
6106 }
6107 }
6108 }
6109 // Run ingestion jobs.
6110 if (status.ok()) {
6111 for (size_t i = 0; i != num_cfs; ++i) {
6112 mutex_.AssertHeld();
6113 status = ingestion_jobs[i].Run();
6114 if (!status.ok()) {
6115 break;
6116 }
6117 ingestion_jobs[i].RegisterRange();
6118 }
6119 }
6120 if (status.ok()) {
6121 ReadOptions read_options;
6122 read_options.fill_cache = args[0].options.fill_cache;
6123 autovector<ColumnFamilyData*> cfds_to_commit;
6124 autovector<const MutableCFOptions*> mutable_cf_options_list;
6125 autovector<autovector<VersionEdit*>> edit_lists;
6126 uint32_t num_entries = 0;
6127 for (size_t i = 0; i != num_cfs; ++i) {
6128 auto* cfd = ingestion_jobs[i].GetColumnFamilyData();
6129 assert(!cfd->IsDropped());
6130 cfds_to_commit.push_back(cfd);
6131 mutable_cf_options_list.push_back(cfd->GetLatestMutableCFOptions());
6132 autovector<VersionEdit*> edit_list;
6133 edit_list.push_back(ingestion_jobs[i].edit());
6134 edit_lists.push_back(edit_list);
6135 ++num_entries;
6136 }
6137 // Mark the version edits as an atomic group if the number of version
6138 // edits exceeds 1.
6139 if (cfds_to_commit.size() > 1) {
6140 for (auto& edits : edit_lists) {
6141 assert(edits.size() == 1);
6142 edits[0]->MarkAtomicGroup(--num_entries);
6143 }
6144 assert(0 == num_entries);
6145 }
6146 status = versions_->LogAndApply(
6147 cfds_to_commit, mutable_cf_options_list, read_options, write_options,
6148
6149 edit_lists, &mutex_, directories_.GetDbDir());
6150 // It is safe to update VersionSet last seqno here after LogAndApply since
6151 // LogAndApply persists last sequence number from VersionEdits,
6152 // which are from file's largest seqno and not from VersionSet.
6153 //
6154 // It is necessary to update last seqno here since LogAndApply releases
6155 // mutex when persisting MANIFEST file, and the snapshots taken during
6156 // that period will not be stable if VersionSet last seqno is updated
6157 // before LogAndApply.
6158 int consumed_seqno_count =
6159 ingestion_jobs[0].ConsumedSequenceNumbersCount();
6160 for (size_t i = 1; i != num_cfs; ++i) {
6161 consumed_seqno_count =
6162 std::max(consumed_seqno_count,
6163 ingestion_jobs[i].ConsumedSequenceNumbersCount());
6164 }
6165 if (consumed_seqno_count > 0) {
6166 const SequenceNumber last_seqno = versions_->LastSequence();
6167 versions_->SetLastAllocatedSequence(last_seqno + consumed_seqno_count);
6168 versions_->SetLastPublishedSequence(last_seqno + consumed_seqno_count);
6169 versions_->SetLastSequence(last_seqno + consumed_seqno_count);
6170 }
6171 }
6172
6173 for (auto& job : ingestion_jobs) {
6174 job.UnregisterRange();
6175 }
6176
6177 if (status.ok()) {
6178 for (size_t i = 0; i != num_cfs; ++i) {
6179 auto* cfd = ingestion_jobs[i].GetColumnFamilyData();
6180 assert(!cfd->IsDropped());
6181 InstallSuperVersionAndScheduleWork(cfd, &sv_ctxs[i],
6182 *cfd->GetLatestMutableCFOptions());
6183#ifndef NDEBUG
6184 if (0 == i && num_cfs > 1) {
6185 TEST_SYNC_POINT("DBImpl::IngestExternalFiles:InstallSVForFirstCF:0");
6186 TEST_SYNC_POINT("DBImpl::IngestExternalFiles:InstallSVForFirstCF:1");
6187 }
6188#endif // !NDEBUG
6189 }
6190 } else if (versions_->io_status().IsIOError()) {
6191 // Error while writing to MANIFEST.
6192 // In fact, versions_->io_status() can also be the result of renaming
6193 // CURRENT file. With current code, it's just difficult to tell. So just
6194 // be pessimistic and try write to a new MANIFEST.
6195 // TODO: distinguish between MANIFEST write and CURRENT renaming
6196 const IOStatus& io_s = versions_->io_status();
6197 // Should handle return error?
6198 error_handler_.SetBGError(io_s, BackgroundErrorReason::kManifestWrite);
6199 }
6200
6201 // Resume writes to the DB
6202 if (two_write_queues_) {
6204 }
6206
6207 if (status.ok()) {
6208 for (auto& job : ingestion_jobs) {
6209 job.UpdateStats();
6210 }
6211 }
6212 ReleaseFileNumberFromPendingOutputs(pending_output_elem);
6213 num_running_ingest_file_ -= static_cast<int>(num_cfs);
6214 if (0 == num_running_ingest_file_) {
6215 bg_cv_.SignalAll();
6216 }
6217 TEST_SYNC_POINT("DBImpl::AddFile:MutexUnlock");
6218 }
6219 // mutex_ is unlocked here
6220
6221 // Cleanup
6222 for (size_t i = 0; i != num_cfs; ++i) {
6223 sv_ctxs[i].Clean();
6224 // This may rollback jobs that have completed successfully. This is
6225 // intended for atomicity.
6226 ingestion_jobs[i].Cleanup(status);
6227 }
6228 if (status.ok()) {
6229 for (size_t i = 0; i != num_cfs; ++i) {
6230 auto* cfd = ingestion_jobs[i].GetColumnFamilyData();
6231 if (!cfd->IsDropped()) {
6232 NotifyOnExternalFileIngested(cfd, ingestion_jobs[i]);
6233 }
6234 }
6235 }
6236 return status;
6237}
void NotifyOnExternalFileIngested(ColumnFamilyData *cfd, const ExternalSstFileIngestionJob &ingestion_job)
Definition db_impl.cc:6641
Status ReserveFileNumbersBeforeIngestion(ColumnFamilyData *cfd, uint64_t num, std::unique_ptr< std::list< uint64_t >::iterator > &pending_output_elem, uint64_t *next_file_number)
Definition db_impl.cc:6742
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IngestWBWI()

Status ROCKSDB_NAMESPACE::DBImpl::IngestWBWI ( std::shared_ptr< WriteBatchWithIndex > wbwi,
const WBWIMemTable::SeqnoRange & assigned_seqno,
uint64_t min_prep_log,
SequenceNumber last_seqno,
bool memtable_updated,
bool ignore_missing_cf )
protected

db_impl_write.cc 파일의 193 번째 라인에서 정의되었습니다.

197 {
198 // Keys in new memtable have seqno > last_seqno_after_ingest >= keys in wbwi.
199 assert(assigned_seqno.upper_bound <= last_seqno_after_ingest);
200 // Keys in the current memtable have seqno <= LastSequence() < keys in wbwi.
201 assert(assigned_seqno.lower_bound > versions_->LastSequence());
202 autovector<ReadOnlyMemTable*> memtables;
203 autovector<ColumnFamilyData*> cfds;
204 InstrumentedMutexLock lock(&mutex_);
205 ColumnFamilySet* cf_set = versions_->GetColumnFamilySet();
206
207 // Create WBWIMemTables
208 for (const auto [cf_id, stat] : wbwi->GetCFStats()) {
209 ColumnFamilyData* cfd = cf_set->GetColumnFamily(cf_id);
210 if (!cfd) {
211 if (ignore_missing_cf) {
212 continue;
213 }
214 for (auto mem : memtables) {
215 mem->Unref();
216 delete mem;
217 }
218 for (auto cfd_ptr : cfds) {
219 cfd_ptr->UnrefAndTryDelete();
220 }
221 Status s = Status::InvalidArgument(
222 "Invalid column family id from WriteBatchWithIndex: " +
223 std::to_string(cf_id));
224 if (memtable_updated) {
225 s = Status::Corruption(
226 "Part of the write batch is applied. Memtable is in a inconsistent "
227 "state. " +
228 s.ToString());
229 error_handler_.SetBGError(s, BackgroundErrorReason::kMemTable);
230 }
231
232 return s;
233 }
234 WBWIMemTable* wbwi_memtable =
235 new WBWIMemTable(wbwi, cfd->user_comparator(), cf_id, cfd->ioptions(),
236 cfd->GetLatestMutableCFOptions(), stat);
237 wbwi_memtable->Ref();
238 wbwi_memtable->AssignSequenceNumbers(assigned_seqno);
239 // This is needed to keep the WAL that contains Prepare alive until
240 // committed data in this memtable is persisted.
241 wbwi_memtable->SetMinPrepLog(prep_log);
242 memtables.push_back(wbwi_memtable);
243 cfd->Ref();
244 cfds.push_back(cfd);
245 }
246
247 // Stop writes to the DB by entering both write threads
248 WriteThread::Writer nonmem_w;
249 if (two_write_queues_) {
250 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
251 }
253
254 // Switch memtable and add WBWIMemTables
255 Status s;
256 for (size_t i = 0; i < memtables.size(); ++i) {
258 // NOTE: to support atomic flush, need to call
259 // SelectColumnFamiliesForAtomicFlush()
260 WriteContext write_context;
261 // TODO: not switch on empty memtable, may need to update metadata
262 // like NextLogNumber(), earliest_seqno and memtable id.
263 s = SwitchMemtable(cfds[i], &write_context, memtables[i],
264 last_seqno_after_ingest);
265 if (!s.ok()) {
266 // SwitchMemtable() can only fail if a new WAL is to be created, this
267 // should only happen for the first call to SwitchMemtable(). log will
268 // be empty and no new WAL is created for the rest of the calls.
269 assert(i == 0);
270 if (i != 0 || memtable_updated) {
271 // escalate error to non-recoverable
272 s = Status::Corruption(
273 "Part of the write batch is applied. Memtable is in a inconsistent "
274 "state. " +
275 s.ToString());
276 error_handler_.SetBGError(s, BackgroundErrorReason::kMemTable);
277 } else {
278 // SwitchMemtable() already sets appropriate bg error
279 }
280 for (size_t j = i; j < memtables.size(); j++) {
281 memtables[j]->Unref();
282 delete memtables[j];
283 }
284 break;
285 }
286 }
287 for (size_t i = 0; i < cfds.size(); ++i) {
288 if (cfds[i]->UnrefAndTryDelete()) {
289 cfds[i] = nullptr;
290 }
291 }
292
293 // exit the second queue before returning
294 if (two_write_queues_) {
296 }
297 if (s.ok()) {
298 // Trigger flushes for the new immutable memtables.
299 for (const auto cfd : cfds) {
300 if (cfd == nullptr) {
301 continue;
302 }
303 cfd->imm()->FlushRequested();
304 FlushRequest flush_req;
305 // TODO: a new flush reason for ingesting memtable
306 GenerateFlushRequest({cfd}, FlushReason::kExternalFileIngestion,
307 &flush_req);
308 EnqueuePendingFlush(flush_req);
309 }
311 }
312 return s;
313}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ InitPersistStatsColumnFamily()

Status ROCKSDB_NAMESPACE::DBImpl::InitPersistStatsColumnFamily ( )
private

db_impl_open.cc 파일의 951 번째 라인에서 정의되었습니다.

951 {
952 mutex_.AssertHeld();
953 assert(!persist_stats_cf_handle_);
954 ColumnFamilyData* persistent_stats_cfd =
955 versions_->GetColumnFamilySet()->GetColumnFamily(
956 kPersistentStatsColumnFamilyName);
957 persistent_stats_cfd_exists_ = persistent_stats_cfd != nullptr;
958
959 Status s;
960 if (persistent_stats_cfd != nullptr) {
961 // We are recovering from a DB which already contains persistent stats CF,
962 // the CF is already created in VersionSet::ApplyOneVersionEdit, but
963 // column family handle was not. Need to explicitly create handle here.
965 new ColumnFamilyHandleImpl(persistent_stats_cfd, this, &mutex_);
966 } else {
967 mutex_.Unlock();
968 ColumnFamilyHandle* handle = nullptr;
969 ColumnFamilyOptions cfo;
971 s = CreateColumnFamilyImpl(ReadOptions(Env::IOActivity::kDBOpen),
972 WriteOptions(Env::IOActivity::kDBOpen), cfo,
973 kPersistentStatsColumnFamilyName, &handle);
974 persist_stats_cf_handle_ = static_cast<ColumnFamilyHandleImpl*>(handle);
975 mutex_.Lock();
976 }
977 return s;
978}
void OptimizeForPersistentStats(ColumnFamilyOptions *cfo)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ InsertRecoveredTransaction()

void ROCKSDB_NAMESPACE::DBImpl::InsertRecoveredTransaction ( const uint64_t log,
const std::string & name,
WriteBatch * batch,
SequenceNumber seq,
size_t batch_cnt,
bool unprepared_batch )
inline

db_impl.h 파일의 1017 번째 라인에서 정의되었습니다.

1019 {
1020 // For WriteUnpreparedTxn, InsertRecoveredTransaction is called multiple
1021 // times for every unprepared batch encountered during recovery.
1022 //
1023 // If the transaction is prepared, then the last call to
1024 // InsertRecoveredTransaction will have unprepared_batch = false.
1025 auto rtxn = recovered_transactions_.find(name);
1026 if (rtxn == recovered_transactions_.end()) {
1027 recovered_transactions_[name] = new RecoveredTransaction(
1028 log, name, batch, seq, batch_cnt, unprepared_batch);
1029 } else {
1030 rtxn->second->AddBatch(seq, log, batch, batch_cnt, unprepared_batch);
1031 }
1033 }

◆ InstallSeqnoToTimeMappingInSV()

void ROCKSDB_NAMESPACE::DBImpl::InstallSeqnoToTimeMappingInSV ( std::vector< SuperVersionContext > * sv_contexts)

db_impl.cc 파일의 6917 번째 라인에서 정의되었습니다.

6918 {
6919 mutex_.AssertHeld();
6920 std::shared_ptr<SeqnoToTimeMapping> new_seqno_to_time_mapping =
6921 std::make_shared<SeqnoToTimeMapping>();
6922 new_seqno_to_time_mapping->CopyFrom(seqno_to_time_mapping_);
6923 for (ColumnFamilyData* cfd : *versions_->GetColumnFamilySet()) {
6924 if (cfd->IsDropped()) {
6925 continue;
6926 }
6927 sv_contexts->emplace_back(/*create_superversion=*/true);
6928 sv_contexts->back().new_seqno_to_time_mapping = new_seqno_to_time_mapping;
6929 cfd->InstallSuperVersion(&sv_contexts->back(),
6930 *(cfd->GetLatestMutableCFOptions()));
6931 }
6932 bg_cv_.SignalAll();
6933}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ InstallSuperVersionAndScheduleWork()

void ROCKSDB_NAMESPACE::DBImpl::InstallSuperVersionAndScheduleWork ( ColumnFamilyData * cfd,
SuperVersionContext * sv_context,
const MutableCFOptions & mutable_cf_options )
private

db_impl_compaction_flush.cc 파일의 4287 번째 라인에서 정의되었습니다.

4289 {
4290 mutex_.AssertHeld();
4291
4292 // Update max_total_in_memory_state_
4293 size_t old_memtable_size = 0;
4294 auto* old_sv = cfd->GetSuperVersion();
4295 if (old_sv) {
4296 old_memtable_size = old_sv->mutable_cf_options.write_buffer_size *
4297 old_sv->mutable_cf_options.max_write_buffer_number;
4298 }
4299
4300 // this branch is unlikely to step in
4301 if (UNLIKELY(sv_context->new_superversion == nullptr)) {
4302 sv_context->NewSuperVersion();
4303 }
4304 cfd->InstallSuperVersion(sv_context, mutable_cf_options);
4305
4306 // There may be a small data race here. The snapshot tricking bottommost
4307 // compaction may already be released here. But assuming there will always be
4308 // newer snapshot created and released frequently, the compaction will be
4309 // triggered soon anyway.
4310 bottommost_files_mark_threshold_ = kMaxSequenceNumber;
4312 for (auto* my_cfd : *versions_->GetColumnFamilySet()) {
4313 if (!my_cfd->ioptions()->allow_ingest_behind) {
4315 bottommost_files_mark_threshold_,
4316 my_cfd->current()->storage_info()->bottommost_files_mark_threshold());
4317 }
4319 std::min(standalone_range_deletion_files_mark_threshold_,
4320 cfd->current()
4321 ->storage_info()
4322 ->standalone_range_tombstone_files_mark_threshold());
4323 }
4324
4325 // Whenever we install new SuperVersion, we might need to issue new flushes or
4326 // compactions.
4329
4330 // Update max_total_in_memory_state_
4332 mutable_cf_options.write_buffer_size *
4333 mutable_cf_options.max_write_buffer_number;
4334}
void EnqueuePendingCompaction(ColumnFamilyData *cfd)
SequenceNumber bottommost_files_mark_threshold_
Definition db_impl.h:2940
SequenceNumber standalone_range_deletion_files_mark_threshold_
Definition db_impl.h:2944
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ InvokeWalFilterIfNeededOnColumnFamilyToWalNumberMap()

void ROCKSDB_NAMESPACE::DBImpl::InvokeWalFilterIfNeededOnColumnFamilyToWalNumberMap ( )
protected

db_impl_open.cc 파일의 993 번째 라인에서 정의되었습니다.

993 {
994 if (immutable_db_options_.wal_filter == nullptr) {
995 return;
996 }
997 assert(immutable_db_options_.wal_filter != nullptr);
998 WalFilter& wal_filter = *(immutable_db_options_.wal_filter);
999
1000 std::map<std::string, uint32_t> cf_name_id_map;
1001 std::map<uint32_t, uint64_t> cf_lognumber_map;
1002 assert(versions_);
1003 assert(versions_->GetColumnFamilySet());
1004 for (auto cfd : *versions_->GetColumnFamilySet()) {
1005 assert(cfd);
1006 cf_name_id_map.insert(std::make_pair(cfd->GetName(), cfd->GetID()));
1007 cf_lognumber_map.insert(std::make_pair(cfd->GetID(), cfd->GetLogNumber()));
1008 }
1009
1010 wal_filter.ColumnFamilyLogNumberMap(cf_lognumber_map, cf_name_id_map);
1011}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ InvokeWalFilterIfNeededOnWalRecord()

bool ROCKSDB_NAMESPACE::DBImpl::InvokeWalFilterIfNeededOnWalRecord ( uint64_t wal_number,
const std::string & wal_fname,
log::Reader::Reporter & reporter,
Status & status,
bool & stop_replay,
WriteBatch & batch )
protected

db_impl_open.cc 파일의 1013 번째 라인에서 정의되었습니다.

1018 {
1019 if (immutable_db_options_.wal_filter == nullptr) {
1020 return true;
1021 }
1022 assert(immutable_db_options_.wal_filter != nullptr);
1023 WalFilter& wal_filter = *(immutable_db_options_.wal_filter);
1024
1025 WriteBatch new_batch;
1026 bool batch_changed = false;
1027
1028 bool process_current_record = true;
1029
1030 WalFilter::WalProcessingOption wal_processing_option =
1031 wal_filter.LogRecordFound(wal_number, wal_fname, batch, &new_batch,
1032 &batch_changed);
1033
1034 switch (wal_processing_option) {
1035 case WalFilter::WalProcessingOption::kContinueProcessing:
1036 // do nothing, proceeed normally
1037 break;
1038 case WalFilter::WalProcessingOption::kIgnoreCurrentRecord:
1039 // skip current record
1040 process_current_record = false;
1041 break;
1042 case WalFilter::WalProcessingOption::kStopReplay:
1043 // skip current record and stop replay
1044 process_current_record = false;
1045 stop_replay = true;
1046 break;
1047 case WalFilter::WalProcessingOption::kCorruptedRecord: {
1048 status = Status::Corruption("Corruption reported by Wal Filter ",
1049 wal_filter.Name());
1050 MaybeIgnoreError(&status);
1051 if (!status.ok()) {
1052 process_current_record = false;
1053 reporter.Corruption(batch.GetDataSize(), status);
1054 }
1055 break;
1056 }
1057 default: {
1058 // logical error which should not happen. If RocksDB throws, we would
1059 // just do `throw std::logic_error`.
1060 assert(false);
1061 status = Status::NotSupported(
1062 "Unknown WalProcessingOption returned by Wal Filter ",
1063 wal_filter.Name());
1064 MaybeIgnoreError(&status);
1065 if (!status.ok()) {
1066 // Ignore the error with current record processing.
1067 stop_replay = true;
1068 }
1069 break;
1070 }
1071 }
1072
1073 if (!process_current_record) {
1074 return false;
1075 }
1076
1077 if (batch_changed) {
1078 // Make sure that the count in the new batch is
1079 // within the orignal count.
1080 int new_count = WriteBatchInternal::Count(&new_batch);
1081 int original_count = WriteBatchInternal::Count(&batch);
1082 if (new_count > original_count) {
1085 "Recovering log #%" PRIu64
1086 " mode %d log filter %s returned "
1087 "more records (%d) than original (%d) which is not allowed. "
1088 "Aborting recovery.",
1089 wal_number, static_cast<int>(immutable_db_options_.wal_recovery_mode),
1090 wal_filter.Name(), new_count, original_count);
1091 status = Status::NotSupported(
1092 "More than original # of records "
1093 "returned by Wal Filter ",
1094 wal_filter.Name());
1095 return false;
1096 }
1097 // Set the same sequence number in the new_batch
1098 // as the original batch.
1099 WriteBatchInternal::SetSequence(&new_batch,
1100 WriteBatchInternal::Sequence(&batch));
1101 batch = new_batch;
1102 }
1103 return true;
1104}
void MaybeIgnoreError(Status *s) const
Definition db_impl.cc:771
#define ROCKS_LOG_FATAL(LGR, FMT,...)
Definition logging.h:47
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IsFileDeletionsEnabled()

bool ROCKSDB_NAMESPACE::DBImpl::IsFileDeletionsEnabled ( ) const
virtual

db_impl_files.cc 파일의 111 번째 라인에서 정의되었습니다.

111 {
113}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IsRecoveryFlush()

static bool ROCKSDB_NAMESPACE::DBImpl::IsRecoveryFlush ( FlushReason flush_reason)
inlinestaticprivate

db_impl.h 파일의 1940 번째 라인에서 정의되었습니다.

1940 {
1941 return flush_reason == FlushReason::kErrorRecoveryRetryFlush ||
1942 flush_reason == FlushReason::kErrorRecovery;
1943 }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ KeyMayExist() [1/4]

virtual bool ROCKSDB_NAMESPACE::DB::KeyMayExist ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
std::string * value,
bool * value_found = nullptr )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 973 번째 라인에서 정의되었습니다.

975 {
976 return KeyMayExist(options, column_family, key, value,
977 /*timestamp=*/nullptr, value_found);
978 }
bool KeyMayExist(const ReadOptions &options, ColumnFamilyHandle *column_family, const Slice &key, std::string *value, std::string *timestamp, bool *value_found=nullptr) override
Definition db_impl.cc:3807

◆ KeyMayExist() [2/4]

bool ROCKSDB_NAMESPACE::DBImpl::KeyMayExist ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
std::string * value,
std::string * timestamp,
bool * value_found = nullptr )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 3807 번째 라인에서 정의되었습니다.

3810 {
3811 assert(read_options.io_activity == Env::IOActivity::kUnknown);
3812
3813 if (value_found != nullptr) {
3814 // falsify later if key-may-exist but can't fetch value
3815 *value_found = true;
3816 }
3817 // TODO: plumb Env::IOActivity, Env::IOPriority
3818 ReadOptions roptions = read_options;
3819 roptions.read_tier = kBlockCacheTier; // read from block cache only
3820 PinnableSlice pinnable_val;
3821 GetImplOptions get_impl_options;
3822 get_impl_options.column_family = column_family;
3823 get_impl_options.value = &pinnable_val;
3824 get_impl_options.value_found = value_found;
3825 get_impl_options.timestamp = timestamp;
3826 auto s = GetImpl(roptions, key, get_impl_options);
3827 if (value_found && *value_found && value) {
3828 value->assign(pinnable_val.data(), pinnable_val.size());
3829 }
3830
3831 // If block_cache is enabled and the index block of the table didn't
3832 // not present in block_cache, the return value will be Status::Incomplete.
3833 // In this case, key may still exist in the table.
3834 return s.ok() || s.IsIncomplete();
3835}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ KeyMayExist() [3/4]

virtual bool ROCKSDB_NAMESPACE::DB::KeyMayExist ( const ReadOptions & options,
const Slice & key,
std::string * value,
bool * value_found = nullptr )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 980 번째 라인에서 정의되었습니다.

981 {
982 return KeyMayExist(options, DefaultColumnFamily(), key, value, value_found);
983 }

◆ KeyMayExist() [4/4]

virtual bool ROCKSDB_NAMESPACE::DB::KeyMayExist ( const ReadOptions & options,
const Slice & key,
std::string * value,
std::string * timestamp,
bool * value_found = nullptr )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 985 번째 라인에서 정의되었습니다.

987 {
988 return KeyMayExist(options, DefaultColumnFamily(), key, value, timestamp,
989 value_found);
990 }

◆ Level0StopWriteTrigger() [1/2]

virtual int ROCKSDB_NAMESPACE::DB::Level0StopWriteTrigger ( )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1624 번째 라인에서 정의되었습니다.

1624 {
1626 }
int Level0StopWriteTrigger(ColumnFamilyHandle *column_family) override

◆ Level0StopWriteTrigger() [2/2]

int ROCKSDB_NAMESPACE::DBImpl::Level0StopWriteTrigger ( ColumnFamilyHandle * column_family)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 1922 번째 라인에서 정의되었습니다.

1922 {
1923 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1924 InstrumentedMutexLock l(&mutex_);
1925 return cfh->cfd()
1926 ->GetSuperVersion()
1927 ->mutable_cf_options.level0_stop_writes_trigger;
1928}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ LoadSnapshots()

void ROCKSDB_NAMESPACE::DBImpl::LoadSnapshots ( std::vector< SequenceNumber > * snap_vector,
SequenceNumber * oldest_write_conflict_snapshot,
const SequenceNumber & max_seq ) const
inline

db_impl.h 파일의 885 번째 라인에서 정의되었습니다.

887 {
888 InstrumentedMutexLock l(mutex());
889 snapshots().GetAll(snap_vector, oldest_write_conflict_snapshot, max_seq);
890 }
const SnapshotList & snapshots() const
Definition db_impl.h:879
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ LockWAL()

Status ROCKSDB_NAMESPACE::DBImpl::LockWAL ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 1766 번째 라인에서 정의되었습니다.

1766 {
1767 {
1768 InstrumentedMutexLock lock(&mutex_);
1769 if (lock_wal_count_ > 0) {
1770 assert(lock_wal_write_token_);
1772 } else {
1773 // NOTE: this will "unnecessarily" wait for other non-LockWAL() write
1774 // stalls to clear before LockWAL returns, however fixing that would
1775 // not be simple because if we notice the primary queue is already
1776 // stalled, that stall might clear while we release DB mutex in
1777 // EnterUnbatched() for the nonmem queue. And if we work around that in
1778 // the naive way, we could deadlock by locking the two queues in different
1779 // orders.
1780
1781 WriteThread::Writer w;
1782 write_thread_.EnterUnbatched(&w, &mutex_);
1783 WriteThread::Writer nonmem_w;
1784 if (two_write_queues_) {
1785 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
1786 }
1787
1788 // NOTE: releasing mutex in EnterUnbatched might mean we are actually
1789 // now lock_wal_count > 0
1790 if (lock_wal_count_ == 0) {
1791 assert(!lock_wal_write_token_);
1793 }
1795
1796 if (two_write_queues_) {
1798 }
1800 }
1801 }
1802 // NOTE: avoid I/O holding DB mutex
1803 Status s = FlushWAL(/*sync=*/false);
1804 if (!s.ok()) {
1805 // Non-OK return should not be in locked state
1807 }
1808 return s;
1809}
Status UnlockWAL() override
Definition db_impl.cc:1811
std::unique_ptr< WriteControllerToken > lock_wal_write_token_
Definition db_impl.h:3020
std::unique_ptr< WriteControllerToken > GetStopToken()
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ LogAndApplyForRecovery()

Status ROCKSDB_NAMESPACE::DBImpl::LogAndApplyForRecovery ( const RecoveryContext & recovery_ctx)
protected

db_impl_open.cc 파일의 980 번째 라인에서 정의되었습니다.

980 {
981 mutex_.AssertHeld();
982 assert(versions_->descriptor_log_ == nullptr);
983 const ReadOptions read_options(Env::IOActivity::kDBOpen);
984 const WriteOptions write_options(Env::IOActivity::kDBOpen);
985
986 Status s = versions_->LogAndApply(recovery_ctx.cfds_,
987 recovery_ctx.mutable_cf_opts_, read_options,
988 write_options, recovery_ctx.edit_lists_,
989 &mutex_, directories_.GetDbDir());
990 return s;
991}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ logs_with_prep_tracker()

LogsWithPrepTracker * ROCKSDB_NAMESPACE::DBImpl::logs_with_prep_tracker ( )
inline

db_impl.h 파일의 823 번째 라인에서 정의되었습니다.

823 {
825 }

◆ MarkAsGrabbedForPurge()

void ROCKSDB_NAMESPACE::DBImpl::MarkAsGrabbedForPurge ( uint64_t file_number)
private

db_impl_compaction_flush.cc 파일의 4349 번째 라인에서 정의되었습니다.

4349 {
4350 files_grabbed_for_purge_.insert(file_number);
4351}
std::unordered_set< uint64_t > files_grabbed_for_purge_
Definition db_impl.h:2850
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MarkLogsNotSynced()

void ROCKSDB_NAMESPACE::DBImpl::MarkLogsNotSynced ( uint64_t up_to)
private

db_impl.cc 파일의 1891 번째 라인에서 정의되었습니다.

1891 {
1893 for (auto it = logs_.begin(); it != logs_.end() && it->number <= up_to;
1894 ++it) {
1895 auto& wal = *it;
1896 wal.FinishSync();
1897 }
1899}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MarkLogsSynced()

void ROCKSDB_NAMESPACE::DBImpl::MarkLogsSynced ( uint64_t up_to,
bool synced_dir,
VersionEdit * edit )
private

db_impl.cc 파일의 1849 번째 라인에서 정의되었습니다.

1850 {
1852 if (synced_dir && logfile_number_ == up_to) {
1853 log_dir_synced_ = true;
1854 }
1855 for (auto it = logs_.begin(); it != logs_.end() && it->number <= up_to;) {
1856 auto& wal = *it;
1857 assert(wal.IsSyncing());
1858
1859 if (wal.number < logs_.back().number) {
1860 // Inactive WAL
1862 wal.GetPreSyncSize() > 0) {
1863 synced_wals->AddWal(wal.number, WalMetadata(wal.GetPreSyncSize()));
1864 }
1865 // Reclaim closed WALs (wal.writer->file() == nullptr), and if we don't
1866 // need to close before that (background_close_inactive_wals) we can
1867 // opportunistically reclaim WALs that happen to be fully synced.
1868 // (Probably not worth extra code and mutex release to opportunistically
1869 // close WALs that became eligible since last holding the mutex.
1870 // FindObsoleteFiles can take care of it.)
1871 if (wal.writer->file() == nullptr ||
1873 wal.GetPreSyncSize() == wal.writer->file()->GetFlushedSize())) {
1874 // Fully synced
1875 logs_to_free_.push_back(wal.ReleaseWriter());
1876 it = logs_.erase(it);
1877 } else {
1878 wal.FinishSync();
1879 ++it;
1880 }
1881 } else {
1882 assert(wal.number == logs_.back().number);
1883 // Active WAL
1884 wal.FinishSync();
1885 ++it;
1886 }
1887 }
1889}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MaxMemCompactionLevel() [1/2]

virtual int ROCKSDB_NAMESPACE::DB::MaxMemCompactionLevel ( )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1618 번째 라인에서 정의되었습니다.

1618 {
1620 }
int MaxMemCompactionLevel(ColumnFamilyHandle *column_family) override

◆ MaxMemCompactionLevel() [2/2]

int ROCKSDB_NAMESPACE::DBImpl::MaxMemCompactionLevel ( ColumnFamilyHandle * column_family)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 1918 번째 라인에서 정의되었습니다.

1918 {
1919 return 0;
1920}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MaybeFlushStatsCF()

void ROCKSDB_NAMESPACE::DBImpl::MaybeFlushStatsCF ( autovector< ColumnFamilyData * > * cfds)
private

db_impl_write.cc 파일의 2257 번째 라인에서 정의되었습니다.

2257 {
2258 assert(cfds != nullptr);
2259 if (!cfds->empty() && immutable_db_options_.persist_stats_to_disk) {
2260 ColumnFamilyData* cfd_stats =
2261 versions_->GetColumnFamilySet()->GetColumnFamily(
2262 kPersistentStatsColumnFamilyName);
2263 if (cfd_stats != nullptr && !cfd_stats->mem()->IsEmpty()) {
2264 for (ColumnFamilyData* cfd : *cfds) {
2265 if (cfd == cfd_stats) {
2266 // stats CF already included in cfds
2267 return;
2268 }
2269 }
2270 // force flush stats CF when its log number is less than all other CF's
2271 // log numbers
2272 bool force_flush_stats_cf = true;
2273 for (auto* loop_cfd : *versions_->GetColumnFamilySet()) {
2274 if (loop_cfd == cfd_stats) {
2275 continue;
2276 }
2277 if (loop_cfd->GetLogNumber() <= cfd_stats->GetLogNumber()) {
2278 force_flush_stats_cf = false;
2279 }
2280 }
2281 if (force_flush_stats_cf) {
2282 cfds->push_back(cfd_stats);
2284 "Force flushing stats CF with automated flush "
2285 "to avoid holding old logs");
2286 }
2287 }
2288 }
2289}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MaybeIgnoreError()

void ROCKSDB_NAMESPACE::DBImpl::MaybeIgnoreError ( Status * s) const
private

db_impl.cc 파일의 771 번째 라인에서 정의되었습니다.

771 {
772 if (s->ok() || immutable_db_options_.paranoid_checks) {
773 // No change needed
774 } else {
775 ROCKS_LOG_WARN(immutable_db_options_.info_log, "Ignoring error %s",
776 s->ToString().c_str());
777 *s = Status::OK();
778 }
779}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MaybeReleaseTimestampedSnapshotsAndCheck()

Status ROCKSDB_NAMESPACE::DBImpl::MaybeReleaseTimestampedSnapshotsAndCheck ( )
private

db_impl.cc 파일의 520 번째 라인에서 정의되었습니다.

520 {
521 size_t num_snapshots = 0;
522 ReleaseTimestampedSnapshotsOlderThan(std::numeric_limits<uint64_t>::max(),
523 &num_snapshots);
524
525 // If there is unreleased snapshot, fail the close call
526 if (num_snapshots > 0) {
527 return Status::Aborted("Cannot close DB with unreleased snapshot.");
528 }
529
530 return Status::OK();
531}
void ReleaseTimestampedSnapshotsOlderThan(uint64_t ts, size_t *remaining_total_ss=nullptr)
Definition db_impl.cc:4149
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MaybeScheduleFlushOrCompaction()

void ROCKSDB_NAMESPACE::DBImpl::MaybeScheduleFlushOrCompaction ( )
private

db_impl_compaction_flush.cc 파일의 2840 번째 라인에서 정의되었습니다.

2840 {
2841 mutex_.AssertHeld();
2842 TEST_SYNC_POINT("DBImpl::MaybeScheduleFlushOrCompaction:Start");
2843 if (!opened_successfully_) {
2844 // Compaction may introduce data race to DB open
2845 return;
2846 }
2847 if (bg_work_paused_ > 0) {
2848 // we paused the background work
2849 return;
2850 } else if (error_handler_.IsBGWorkStopped() &&
2852 // There has been a hard error and this call is not part of the recovery
2853 // sequence. Bail out here so we don't get into an endless loop of
2854 // scheduling BG work which will again call this function
2855 //
2856 // Note that a non-recovery flush can still be scheduled if
2857 // error_handler_.IsRecoveryInProgress() returns true. We rely on
2858 // BackgroundCallFlush() to check flush reason and drop non-recovery
2859 // flushes.
2860 return;
2861 } else if (shutting_down_.load(std::memory_order_acquire)) {
2862 // DB is being deleted; no more background compactions
2863 return;
2864 }
2865 auto bg_job_limits = GetBGJobLimits();
2866 bool is_flush_pool_empty =
2867 env_->GetBackgroundThreads(Env::Priority::HIGH) == 0;
2868 while (!is_flush_pool_empty && unscheduled_flushes_ > 0 &&
2869 bg_flush_scheduled_ < bg_job_limits.max_flushes) {
2871 "DBImpl::MaybeScheduleFlushOrCompaction:BeforeSchedule",
2872 &unscheduled_flushes_);
2874 FlushThreadArg* fta = new FlushThreadArg;
2875 fta->db_ = this;
2876 fta->thread_pri_ = Env::Priority::HIGH;
2877 env_->Schedule(&DBImpl::BGWorkFlush, fta, Env::Priority::HIGH, this,
2878 &DBImpl::UnscheduleFlushCallback);
2881 "DBImpl::MaybeScheduleFlushOrCompaction:AfterSchedule:0",
2882 &unscheduled_flushes_);
2883 }
2884
2885 // special case -- if high-pri (flush) thread pool is empty, then schedule
2886 // flushes in low-pri (compaction) thread pool.
2887 if (is_flush_pool_empty) {
2888 while (unscheduled_flushes_ > 0 &&
2889 bg_flush_scheduled_ + bg_compaction_scheduled_ <
2890 bg_job_limits.max_flushes) {
2892 FlushThreadArg* fta = new FlushThreadArg;
2893 fta->db_ = this;
2894 fta->thread_pri_ = Env::Priority::LOW;
2895 env_->Schedule(&DBImpl::BGWorkFlush, fta, Env::Priority::LOW, this,
2896 &DBImpl::UnscheduleFlushCallback);
2898 }
2899 }
2900
2901 if (bg_compaction_paused_ > 0) {
2902 // we paused the background compaction
2903 return;
2904 } else if (error_handler_.IsBGWorkStopped()) {
2905 // Compaction is not part of the recovery sequence from a hard error. We
2906 // might get here because recovery might do a flush and install a new
2907 // super version, which will try to schedule pending compactions. Bail
2908 // out here and let the higher level recovery handle compactions
2909 return;
2910 }
2911
2913 // only manual compactions are allowed to run. don't schedule automatic
2914 // compactions
2915 TEST_SYNC_POINT("DBImpl::MaybeScheduleFlushOrCompaction:Conflict");
2916 return;
2917 }
2918
2919 while (bg_compaction_scheduled_ + bg_bottom_compaction_scheduled_ <
2920 bg_job_limits.max_compactions &&
2921 unscheduled_compactions_ > 0) {
2922 CompactionArg* ca = new CompactionArg;
2923 ca->db = this;
2924 ca->compaction_pri_ = Env::Priority::LOW;
2925 ca->prepicked_compaction = nullptr;
2928 env_->Schedule(&DBImpl::BGWorkCompaction, ca, Env::Priority::LOW, this,
2929 &DBImpl::UnscheduleCompactionCallback);
2930 }
2931}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MaybeUpdateNextFileNumber()

Status ROCKSDB_NAMESPACE::DBImpl::MaybeUpdateNextFileNumber ( RecoveryContext * recovery_ctx)
protected

db_impl_files.cc 파일의 1049 번째 라인에서 정의되었습니다.

1049 {
1050 mutex_.AssertHeld();
1051 uint64_t next_file_number = versions_->current_next_file_number();
1052 uint64_t largest_file_number = next_file_number;
1053 Status s;
1054 for (const auto& path : CollectAllDBPaths()) {
1055 std::vector<std::string> files;
1056 s = env_->GetChildren(path, &files);
1057 if (!s.ok()) {
1058 break;
1059 }
1060 for (const auto& fname : files) {
1061 uint64_t number = 0;
1062 FileType type;
1063 if (!ParseFileName(fname, &number, &type)) {
1064 continue;
1065 }
1066 const std::string normalized_fpath = path + kFilePathSeparator + fname;
1067 largest_file_number = std::max(largest_file_number, number);
1068 if ((type == kTableFile || type == kBlobFile)) {
1069 recovery_ctx->existing_data_files_.push_back(normalized_fpath);
1070 }
1071 }
1072 }
1073 if (!s.ok()) {
1074 return s;
1075 }
1076
1077 if (largest_file_number >= next_file_number) {
1078 versions_->next_file_number_.store(largest_file_number + 1);
1079 }
1080
1081 VersionEdit edit;
1082 edit.SetNextFile(versions_->next_file_number_.load());
1083 assert(versions_->GetColumnFamilySet());
1084 ColumnFamilyData* default_cfd = versions_->GetColumnFamilySet()->GetDefault();
1085 assert(default_cfd);
1086 recovery_ctx->UpdateVersionEdits(default_cfd, edit);
1087 return s;
1088}
virtual Status GetChildren(const std::string &dir, std::vector< std::string > *result)=0
constexpr char kFilePathSeparator
Definition filename.h:37
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MCOverlap()

bool ROCKSDB_NAMESPACE::DBImpl::MCOverlap ( ManualCompactionState * m,
ManualCompactionState * m1 )
private

db_impl_compaction_flush.cc 파일의 4174 번째 라인에서 정의되었습니다.

4174 {
4175 if ((m->exclusive) || (m1->exclusive)) {
4176 return true;
4177 }
4178 if (m->cfd != m1->cfd) {
4179 return false;
4180 }
4181 return false;
4182}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MemTableInsertStatusCheck()

void ROCKSDB_NAMESPACE::DBImpl::MemTableInsertStatusCheck ( const Status & memtable_insert_status)
private

db_impl_write.cc 파일의 1383 번째 라인에서 정의되었습니다.

1383 {
1384 // A non-OK status here indicates that the state implied by the
1385 // WAL has diverged from the in-memory state. This could be
1386 // because of a corrupt write_batch (very bad), or because the
1387 // client specified an invalid column family and didn't specify
1388 // ignore_missing_column_families.
1389 if (!status.ok()) {
1390 mutex_.Lock();
1392 error_handler_.SetBGError(status, BackgroundErrorReason::kMemTable);
1393 mutex_.Unlock();
1394 }
1395}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Merge() [1/3]

Status ROCKSDB_NAMESPACE::DBImpl::Merge ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const Slice & ts,
const Slice & value )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 77 번째 라인에서 정의되었습니다.

78 {
79 const Status s = FailIfTsMismatchCf(column_family, ts);
80 if (!s.ok()) {
81 return s;
82 }
83 return DB::Merge(o, column_family, key, ts, val);
84}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ Merge() [2/3]

Status ROCKSDB_NAMESPACE::DBImpl::Merge ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const Slice & value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 63 번째 라인에서 정의되었습니다.

64 {
65 const Status s = FailIfCfHasTs(column_family);
66 if (!s.ok()) {
67 return s;
68 }
69 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
70 if (!cfh->cfd()->ioptions()->merge_operator) {
71 return Status::NotSupported("Provide a merge_operator when opening DB");
72 } else {
73 return DB::Merge(o, column_family, key, val);
74 }
75}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Merge() [3/3]

virtual Status ROCKSDB_NAMESPACE::DB::Merge ( const WriteOptions & options,
const Slice & key,
const Slice & value )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 572 번째 라인에서 정의되었습니다.

573 {
574 return Merge(options, DefaultColumnFamily(), key, value);
575 }
Status Merge(const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &value) override

◆ MergeBatch()

Status ROCKSDB_NAMESPACE::DBImpl::MergeBatch ( const WriteThread::WriteGroup & write_group,
WriteBatch * tmp_batch,
WriteBatch ** merged_batch,
size_t * write_with_wal,
WriteBatch ** to_be_cached_state )
private

db_impl_write.cc 파일의 1510 번째 라인에서 정의되었습니다.

1513 {
1514 assert(write_with_wal != nullptr);
1515 assert(tmp_batch != nullptr);
1516 assert(*to_be_cached_state == nullptr);
1517 *write_with_wal = 0;
1518 auto* leader = write_group.leader;
1519 assert(!leader->disable_wal); // Same holds for all in the batch group
1520 if (write_group.size == 1 && !leader->CallbackFailed() &&
1521 leader->batch->GetWalTerminationPoint().is_cleared()) {
1522 // we simply write the first WriteBatch to WAL if the group only
1523 // contains one batch, that batch should be written to the WAL,
1524 // and the batch is not wanting to be truncated
1525 *merged_batch = leader->batch;
1526 if (WriteBatchInternal::IsLatestPersistentState(*merged_batch)) {
1527 *to_be_cached_state = *merged_batch;
1528 }
1529 *write_with_wal = 1;
1530 } else {
1531 // WAL needs all of the batches flattened into a single batch.
1532 // We could avoid copying here with an iov-like AddRecord
1533 // interface
1534 *merged_batch = tmp_batch;
1535 for (auto writer : write_group) {
1536 if (!writer->CallbackFailed()) {
1537 Status s = WriteBatchInternal::Append(*merged_batch, writer->batch,
1538 /*WAL_only*/ true);
1539 if (!s.ok()) {
1540 tmp_batch->Clear();
1541 return s;
1542 }
1543 if (WriteBatchInternal::IsLatestPersistentState(writer->batch)) {
1544 // We only need to cache the last of such write batch
1545 *to_be_cached_state = writer->batch;
1546 }
1547 (*write_with_wal)++;
1548 }
1549 }
1550 }
1551 // return merged_batch;
1552 return Status::OK();
1553}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MinLogNumberToKeep()

uint64_t ROCKSDB_NAMESPACE::DBImpl::MinLogNumberToKeep ( )

db_impl_files.cc 파일의 27 번째 라인에서 정의되었습니다.

27 {
28 return versions_->min_log_number_to_keep();
29}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MinLogNumberToRecycle()

uint64_t ROCKSDB_NAMESPACE::DBImpl::MinLogNumberToRecycle ( )

db_impl_files.cc 파일의 31 번째 라인에서 정의되었습니다.

uint64_t min_log_number_to_recycle_
Definition db_impl.h:2649
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MinObsoleteSstNumberToKeep()

uint64_t ROCKSDB_NAMESPACE::DBImpl::MinObsoleteSstNumberToKeep ( )

db_impl_files.cc 파일의 33 번째 라인에서 정의되었습니다.

33 {
34 mutex_.AssertHeld();
35 if (!pending_outputs_.empty()) {
36 return *pending_outputs_.begin();
37 }
38 return std::numeric_limits<uint64_t>::max();
39}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MinOptionsFileNumberToKeep()

uint64_t ROCKSDB_NAMESPACE::DBImpl::MinOptionsFileNumberToKeep ( )

db_impl_files.cc 파일의 46 번째 라인에서 정의되었습니다.

46 {
47 mutex_.AssertHeld();
48 if (!min_options_file_numbers_.empty()) {
49 return *min_options_file_numbers_.begin();
50 }
51 return std::numeric_limits<uint64_t>::max();
52}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiCFSnapshot()

template<class T, typename IterDerefFuncType>
Status ROCKSDB_NAMESPACE::DBImpl::MultiCFSnapshot ( const ReadOptions & read_options,
ReadCallback * callback,
IterDerefFuncType iter_deref_func,
T * cf_list,
bool extra_sv_ref,
SequenceNumber * snapshot,
bool * sv_from_thread_local )
private

db_impl.cc 파일의 2635 번째 라인에서 정의되었습니다.

2639 {
2640 PERF_TIMER_GUARD(get_snapshot_time);
2641
2642 assert(sv_from_thread_local);
2643 *sv_from_thread_local = true;
2644 Status s = Status::OK();
2645 const bool check_read_ts =
2646 read_options.timestamp && read_options.timestamp->size() > 0;
2647 // sv_from_thread_local set to false means the SuperVersion to be cleaned up
2648 // is acquired directly via ColumnFamilyData instead of thread local.
2649 const auto sv_cleanup_func = [&]() -> void {
2650 for (auto cf_iter = cf_list->begin(); cf_iter != cf_list->end();
2651 ++cf_iter) {
2652 auto node = iter_deref_func(cf_iter);
2653 SuperVersion* super_version = node->super_version;
2654 ColumnFamilyData* cfd = node->cfd;
2655 if (super_version != nullptr) {
2656 if (*sv_from_thread_local && !extra_sv_ref) {
2657 ReturnAndCleanupSuperVersion(cfd, super_version);
2658 } else {
2659 CleanupSuperVersion(super_version);
2660 }
2661 }
2662 node->super_version = nullptr;
2663 }
2664 };
2665
2666 bool last_try = false;
2667 if (cf_list->size() == 1) {
2668 // Fast path for a single column family. We can simply get the thread local
2669 // super version
2670 auto cf_iter = cf_list->begin();
2671 auto node = iter_deref_func(cf_iter);
2672 if (extra_sv_ref) {
2673 node->super_version = node->cfd->GetReferencedSuperVersion(this);
2674 } else {
2675 node->super_version = GetAndRefSuperVersion(node->cfd);
2676 }
2677 if (check_read_ts) {
2678 s = FailIfReadCollapsedHistory(node->cfd, node->super_version,
2679 *(read_options.timestamp));
2680 }
2681 if (s.ok() && read_options.snapshot != nullptr) {
2682 // Note: In WritePrepared txns this is not necessary but not harmful
2683 // either. Because prep_seq > snapshot => commit_seq > snapshot so if
2684 // a snapshot is specified we should be fine with skipping seq numbers
2685 // that are greater than that.
2686 //
2687 // In WriteUnprepared, we cannot set snapshot in the lookup key because we
2688 // may skip uncommitted data that should be visible to the transaction for
2689 // reading own writes.
2690 *snapshot =
2691 static_cast<const SnapshotImpl*>(read_options.snapshot)->number_;
2692 if (callback) {
2693 *snapshot = std::max(*snapshot, callback->max_visible_seq());
2694 }
2695 } else if (s.ok()) {
2696 // Since we get and reference the super version before getting
2697 // the snapshot number, without a mutex protection, it is possible
2698 // that a memtable switch happened in the middle and not all the
2699 // data for this snapshot is available. But it will contain all
2700 // the data available in the super version we have, which is also
2701 // a valid snapshot to read from.
2702 // We shouldn't get snapshot before finding and referencing the super
2703 // version because a flush happening in between may compact away data for
2704 // the snapshot, but the snapshot is earlier than the data overwriting it,
2705 // so users may see wrong results.
2706 *snapshot = GetLastPublishedSequence();
2707 }
2708 } else {
2709 // If we end up with the same issue of memtable getting sealed during 2
2710 // consecutive retries, it means the write rate is very high. In that case
2711 // it's probably ok to take the mutex on the 3rd try so we can succeed for
2712 // sure.
2713 constexpr int num_retries = 3;
2714 for (int i = 0; i < num_retries; ++i) {
2715 last_try = (i == num_retries - 1);
2716 bool retry = false;
2717
2718 if (i > 0) {
2719 sv_cleanup_func();
2720 }
2721 if (read_options.snapshot == nullptr) {
2722 if (last_try) {
2723 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot::LastTry");
2724 // We're close to max number of retries. For the last retry,
2725 // acquire the lock so we're sure to succeed
2726 mutex_.Lock();
2727 }
2728 *snapshot = GetLastPublishedSequence();
2729 } else {
2730 *snapshot =
2731 static_cast_with_check<const SnapshotImpl>(read_options.snapshot)
2732 ->number_;
2733 }
2734 for (auto cf_iter = cf_list->begin(); cf_iter != cf_list->end();
2735 ++cf_iter) {
2736 auto node = iter_deref_func(cf_iter);
2737 if (!last_try) {
2738 if (extra_sv_ref) {
2739 node->super_version = node->cfd->GetReferencedSuperVersion(this);
2740 } else {
2741 node->super_version = GetAndRefSuperVersion(node->cfd);
2742 }
2743 } else {
2744 node->super_version = node->cfd->GetSuperVersion()->Ref();
2745 }
2746 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot::AfterRefSV");
2747 if (check_read_ts) {
2748 s = FailIfReadCollapsedHistory(node->cfd, node->super_version,
2749 *(read_options.timestamp));
2750 if (!s.ok()) {
2751 // If read timestamp check failed, a.k.a ReadOptions.timestamp <
2752 // super_version.full_history_ts_low. There is no need to continue
2753 // because this check will keep failing for the same and newer
2754 // SuperVersions, instead we fail fast and ask user to provide
2755 // a higher read timestamp.
2756 retry = false;
2757 break;
2758 }
2759 }
2760 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot::BeforeCheckingSnapshot");
2761 if (read_options.snapshot != nullptr || last_try) {
2762 // If user passed a snapshot, then we don't care if a memtable is
2763 // sealed or compaction happens because the snapshot would ensure
2764 // that older key versions are kept around. If this is the last
2765 // retry, then we have the lock so nothing bad can happen
2766 continue;
2767 }
2768 // We could get the earliest sequence number for the whole list of
2769 // memtables, which will include immutable memtables as well, but that
2770 // might be tricky to maintain in case we decide, in future, to do
2771 // memtable compaction.
2772 if (!last_try) {
2773 SequenceNumber seq =
2774 node->super_version->mem->GetEarliestSequenceNumber();
2775 if (seq > *snapshot) {
2776 retry = true;
2777 break;
2778 }
2779 }
2780 }
2781 if (!retry) {
2782 if (last_try) {
2783 mutex_.Unlock();
2784 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot::AfterLastTryRefSV");
2785 }
2786 break;
2787 }
2788 }
2789 }
2790
2791 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot:AfterGetSeqNum1");
2792 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot:AfterGetSeqNum2");
2793 PERF_TIMER_STOP(get_snapshot_time);
2794 *sv_from_thread_local = !last_try;
2795 if (!s.ok()) {
2796 sv_cleanup_func();
2797 }
2798 return s;
2799}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGet() [1/8]

void ROCKSDB_NAMESPACE::DBImpl::MultiGet ( const ReadOptions & _read_options,
const size_t num_keys,
ColumnFamilyHandle ** column_families,
const Slice * keys,
PinnableSlice * values,
std::string * timestamps,
Status * statuses,
const bool sorted_input = false )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 2801 번째 라인에서 정의되었습니다.

2804 {
2805 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
2806 _read_options.io_activity != Env::IOActivity::kMultiGet) {
2807 Status s = Status::InvalidArgument(
2808 "Can only call MultiGet with `ReadOptions::io_activity` is "
2809 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGet`");
2810 for (size_t i = 0; i < num_keys; ++i) {
2811 if (statuses[i].ok()) {
2812 statuses[i] = s;
2813 }
2814 }
2815 return;
2816 }
2817 ReadOptions read_options(_read_options);
2818 if (read_options.io_activity == Env::IOActivity::kUnknown) {
2819 read_options.io_activity = Env::IOActivity::kMultiGet;
2820 }
2821 MultiGetCommon(read_options, num_keys, column_families, keys, values,
2822 /* columns */ nullptr, timestamps, statuses, sorted_input);
2823}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGet() [2/8]

virtual void ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const size_t num_keys,
const Slice * keys,
PinnableSlice * values,
Status * statuses,
const bool sorted_input = false )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 846 번째 라인에서 정의되었습니다.

850 {
851 MultiGet(options, column_family, num_keys, keys, values, nullptr, statuses,
852 sorted_input);
853 }
void MultiGet(const ReadOptions &_read_options, const size_t num_keys, ColumnFamilyHandle **column_families, const Slice *keys, PinnableSlice *values, std::string *timestamps, Status *statuses, const bool sorted_input=false) override
Definition db_impl.cc:2801

◆ MultiGet() [3/8]

void ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const size_t num_keys,
const Slice * keys,
PinnableSlice * values,
std::string * timestamps,
Status * statuses,
const bool sorted_input = false )
finalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 837 번째 라인에서 정의되었습니다.

3029 {
3030 // Use std::array, if possible, to avoid memory allocation overhead
3031 if (num_keys > MultiGetContext::MAX_BATCH_SIZE) {
3032 std::vector<ColumnFamilyHandle*> column_families(num_keys, column_family);
3033 MultiGet(options, num_keys, column_families.data(), keys, values,
3034 timestamps, statuses, sorted_input);
3035 } else {
3036 std::array<ColumnFamilyHandle*, MultiGetContext::MAX_BATCH_SIZE>
3037 column_families;
3038 std::fill(column_families.begin(), column_families.begin() + num_keys,
3039 column_family);
3040 MultiGet(options, num_keys, column_families.data(), keys, values,
3041 timestamps, statuses, sorted_input);
3042 }
3043}

◆ MultiGet() [4/8]

virtual void ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
const size_t num_keys,
ColumnFamilyHandle ** column_families,
const Slice * keys,
PinnableSlice * values,
Status * statuses,
const bool sorted_input = false )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 857 번째 라인에서 정의되었습니다.

860 {
861 MultiGet(options, num_keys, column_families, keys, values, nullptr,
862 statuses, sorted_input);
863 }

◆ MultiGet() [5/8]

virtual std::vector< Status > ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
const std::vector< ColumnFamilyHandle * > & column_families,
const std::vector< Slice > & keys,
std::vector< std::string > * values,
std::vector< std::string > * timestamps )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 741 번째 라인에서 정의되었습니다.

745 {
746 size_t num_keys = keys.size();
747 std::vector<Status> statuses(num_keys);
748 std::vector<PinnableSlice> pin_values(num_keys);
749
750 values->resize(num_keys);
751 if (timestamps) {
752 timestamps->resize(num_keys);
753 }
754 MultiGet(options, num_keys,
755 const_cast<ColumnFamilyHandle**>(column_families.data()),
756 keys.data(), pin_values.data(),
757 timestamps ? timestamps->data() : nullptr, statuses.data(),
758 /*sorted_input=*/false);
759 for (size_t i = 0; i < num_keys; ++i) {
760 if (statuses[i].ok()) {
761 (*values)[i].assign(pin_values[i].data(), pin_values[i].size());
762 }
763 }
764 return statuses;
765 }

◆ MultiGet() [6/8]

virtual std::vector< Status > ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
const std::vector< ColumnFamilyHandle * > & column_family,
const std::vector< Slice > & keys,
std::vector< std::string > * values )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 769 번째 라인에서 정의되었습니다.

772 {
773 values->resize(keys.size());
774 return MultiGet(options, column_family, keys, values, nullptr);
775 }

◆ MultiGet() [7/8]

virtual std::vector< Status > ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
const std::vector< Slice > & keys,
std::vector< std::string > * values )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 779 번째 라인에서 정의되었습니다.

781 {
782 values->resize(keys.size());
783 return MultiGet(
784 options,
785 std::vector<ColumnFamilyHandle*>(keys.size(), DefaultColumnFamily()),
786 keys, values);
787 }

◆ MultiGet() [8/8]

virtual std::vector< Status > ROCKSDB_NAMESPACE::DB::MultiGet ( const ReadOptions & options,
const std::vector< Slice > & keys,
std::vector< std::string > * values,
std::vector< std::string > * timestamps )
inlinefinalvirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 791 번째 라인에서 정의되었습니다.

794 {
795 values->resize(keys.size());
796 return MultiGet(
797 options,
798 std::vector<ColumnFamilyHandle*>(keys.size(), DefaultColumnFamily()),
799 keys, values, timestamps);
800 }

◆ MultiGetCommon() [1/2]

void ROCKSDB_NAMESPACE::DBImpl::MultiGetCommon ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
const size_t num_keys,
const Slice * keys,
PinnableSlice * values,
PinnableWideColumns * columns,
std::string * timestamps,
Status * statuses,
bool sorted_input )
private

db_impl.cc 파일의 3045 번째 라인에서 정의되었습니다.

3050 {
3051 if (tracer_) {
3052 // TODO: This mutex should be removed later, to improve performance when
3053 // tracing is enabled.
3054 InstrumentedMutexLock lock(&trace_mutex_);
3055 if (tracer_) {
3056 // TODO: maybe handle the tracing status?
3057 tracer_->MultiGet(num_keys, column_family, keys).PermitUncheckedError();
3058 }
3059 }
3060 autovector<KeyContext, MultiGetContext::MAX_BATCH_SIZE> key_context;
3061 autovector<KeyContext*, MultiGetContext::MAX_BATCH_SIZE> sorted_keys;
3062 sorted_keys.resize(num_keys);
3063 for (size_t i = 0; i < num_keys; ++i) {
3064 PinnableSlice* val = nullptr;
3065 PinnableWideColumns* col = nullptr;
3066
3067 if (values) {
3068 val = &values[i];
3069 val->Reset();
3070 } else {
3071 assert(columns);
3072
3073 col = &columns[i];
3074 col->Reset();
3075 }
3076
3077 key_context.emplace_back(column_family, keys[i], val, col,
3078 timestamps ? &timestamps[i] : nullptr,
3079 &statuses[i]);
3080 }
3081 for (size_t i = 0; i < num_keys; ++i) {
3082 sorted_keys[i] = &key_context[i];
3083 }
3084 PrepareMultiGetKeys(num_keys, sorted_input, &sorted_keys);
3085 MultiGetWithCallbackImpl(read_options, column_family, nullptr, &sorted_keys);
3086}
void MultiGetWithCallbackImpl(const ReadOptions &read_options, ColumnFamilyHandle *column_family, ReadCallback *callback, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *sorted_keys)
Definition db_impl.cc:3105
void PrepareMultiGetKeys(const size_t num_keys, bool sorted, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *key_ptrs)
Definition db_impl.cc:3011
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetCommon() [2/2]

void ROCKSDB_NAMESPACE::DBImpl::MultiGetCommon ( const ReadOptions & options,
const size_t num_keys,
ColumnFamilyHandle ** column_families,
const Slice * keys,
PinnableSlice * values,
PinnableWideColumns * columns,
std::string * timestamps,
Status * statuses,
bool sorted_input )
private

db_impl.cc 파일의 2825 번째 라인에서 정의되었습니다.

2831 {
2832 if (num_keys == 0) {
2833 return;
2834 }
2835 bool should_fail = false;
2836 for (size_t i = 0; i < num_keys; ++i) {
2837 ColumnFamilyHandle* cfh = column_families[i];
2838 if (read_options.timestamp) {
2839 statuses[i] = FailIfTsMismatchCf(cfh, *(read_options.timestamp));
2840 if (!statuses[i].ok()) {
2841 should_fail = true;
2842 }
2843 } else {
2844 statuses[i] = FailIfCfHasTs(cfh);
2845 if (!statuses[i].ok()) {
2846 should_fail = true;
2847 }
2848 }
2849 }
2850 if (should_fail) {
2851 for (size_t i = 0; i < num_keys; ++i) {
2852 if (statuses[i].ok()) {
2853 statuses[i] = Status::Incomplete(
2854 "DB not queried due to invalid argument(s) in the same MultiGet");
2855 }
2856 }
2857 return;
2858 }
2859
2860 if (tracer_) {
2861 // TODO: This mutex should be removed later, to improve performance when
2862 // tracing is enabled.
2863 InstrumentedMutexLock lock(&trace_mutex_);
2864 if (tracer_) {
2865 // TODO: maybe handle the tracing status?
2866 tracer_->MultiGet(num_keys, column_families, keys).PermitUncheckedError();
2867 }
2868 }
2869
2870 autovector<KeyContext, MultiGetContext::MAX_BATCH_SIZE> key_context;
2871 autovector<KeyContext*, MultiGetContext::MAX_BATCH_SIZE> sorted_keys;
2872 sorted_keys.resize(num_keys);
2873 for (size_t i = 0; i < num_keys; ++i) {
2874 PinnableSlice* val = nullptr;
2875 PinnableWideColumns* col = nullptr;
2876
2877 if (values) {
2878 val = &values[i];
2879 val->Reset();
2880 } else {
2881 assert(columns);
2882
2883 col = &columns[i];
2884 col->Reset();
2885 }
2886
2887 key_context.emplace_back(column_families[i], keys[i], val, col,
2888 timestamps ? &timestamps[i] : nullptr,
2889 &statuses[i]);
2890 }
2891 for (size_t i = 0; i < num_keys; ++i) {
2892 sorted_keys[i] = &key_context[i];
2893 }
2894 PrepareMultiGetKeys(num_keys, sorted_input, &sorted_keys);
2895
2896 autovector<MultiGetKeyRangePerCf, MultiGetContext::MAX_BATCH_SIZE>
2897 key_range_per_cf;
2898 autovector<ColumnFamilySuperVersionPair, MultiGetContext::MAX_BATCH_SIZE>
2899 cf_sv_pairs;
2900 size_t cf_start = 0;
2901 ColumnFamilyHandle* cf = sorted_keys[0]->column_family;
2902
2903 for (size_t i = 0; i < num_keys; ++i) {
2904 KeyContext* key_ctx = sorted_keys[i];
2905 if (key_ctx->column_family != cf) {
2906 key_range_per_cf.emplace_back(cf_start, i - cf_start);
2907 cf_sv_pairs.emplace_back(cf, nullptr);
2908 cf_start = i;
2909 cf = key_ctx->column_family;
2910 }
2911 }
2912
2913 key_range_per_cf.emplace_back(cf_start, num_keys - cf_start);
2914 cf_sv_pairs.emplace_back(cf, nullptr);
2915
2916 SequenceNumber consistent_seqnum = kMaxSequenceNumber;
2917 bool sv_from_thread_local = false;
2918 Status s = MultiCFSnapshot<autovector<ColumnFamilySuperVersionPair,
2919 MultiGetContext::MAX_BATCH_SIZE>>(
2920 read_options, nullptr,
2921 [](autovector<ColumnFamilySuperVersionPair,
2922 MultiGetContext::MAX_BATCH_SIZE>::iterator& cf_iter) {
2923 return &(*cf_iter);
2924 },
2925 &cf_sv_pairs,
2926 /* extra_sv_ref */ false, &consistent_seqnum, &sv_from_thread_local);
2927
2928 if (!s.ok()) {
2929 for (size_t i = 0; i < num_keys; ++i) {
2930 if (statuses[i].ok()) {
2931 statuses[i] = s;
2932 }
2933 }
2934 return;
2935 }
2936
2937 GetWithTimestampReadCallback timestamp_read_callback(0);
2938 ReadCallback* read_callback = nullptr;
2939 if (read_options.timestamp && read_options.timestamp->size() > 0) {
2940 timestamp_read_callback.Refresh(consistent_seqnum);
2941 read_callback = &timestamp_read_callback;
2942 }
2943
2944 assert(key_range_per_cf.size() == cf_sv_pairs.size());
2945 auto key_range_per_cf_iter = key_range_per_cf.begin();
2946 auto cf_sv_pair_iter = cf_sv_pairs.begin();
2947 while (key_range_per_cf_iter != key_range_per_cf.end() &&
2948 cf_sv_pair_iter != cf_sv_pairs.end()) {
2949 s = MultiGetImpl(read_options, key_range_per_cf_iter->start,
2950 key_range_per_cf_iter->num_keys, &sorted_keys,
2951 cf_sv_pair_iter->super_version, consistent_seqnum,
2952 read_callback);
2953 if (!s.ok()) {
2954 break;
2955 }
2956 ++key_range_per_cf_iter;
2957 ++cf_sv_pair_iter;
2958 }
2959 if (!s.ok()) {
2960 assert(s.IsTimedOut() || s.IsAborted());
2961 for (++key_range_per_cf_iter;
2962 key_range_per_cf_iter != key_range_per_cf.end();
2963 ++key_range_per_cf_iter) {
2964 for (size_t i = key_range_per_cf_iter->start;
2965 i < key_range_per_cf_iter->start + key_range_per_cf_iter->num_keys;
2966 ++i) {
2967 *sorted_keys[i]->s = s;
2968 }
2969 }
2970 }
2971
2972 for (const auto& cf_sv_pair : cf_sv_pairs) {
2973 if (sv_from_thread_local) {
2974 ReturnAndCleanupSuperVersion(cf_sv_pair.cfd, cf_sv_pair.super_version);
2975 } else {
2976 TEST_SYNC_POINT("DBImpl::MultiCFSnapshot::BeforeLastTryUnRefSV");
2977 CleanupSuperVersion(cf_sv_pair.super_version);
2978 }
2979 }
2980}
Status MultiCFSnapshot(const ReadOptions &read_options, ReadCallback *callback, IterDerefFuncType iter_deref_func, T *cf_list, bool extra_sv_ref, SequenceNumber *snapshot, bool *sv_from_thread_local)
Definition db_impl.cc:2635
Status MultiGetImpl(const ReadOptions &read_options, size_t start_key, size_t num_keys, autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > *sorted_keys, SuperVersion *sv, SequenceNumber snap_seqnum, ReadCallback *callback)
Definition db_impl.cc:3175
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetEntity() [1/3]

void ROCKSDB_NAMESPACE::DBImpl::MultiGetEntity ( const ReadOptions & options,
ColumnFamilyHandle * column_family,
size_t num_keys,
const Slice * keys,
PinnableWideColumns * results,
Status * statuses,
bool sorted_input )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 3364 번째 라인에서 정의되었습니다.

3367 {
3368 assert(statuses);
3369
3370 if (!column_family) {
3371 const Status s = Status::InvalidArgument(
3372 "Cannot call MultiGetEntity without a column family handle");
3373 for (size_t i = 0; i < num_keys; ++i) {
3374 statuses[i] = s;
3375 }
3376
3377 return;
3378 }
3379
3380 if (!keys) {
3381 const Status s =
3382 Status::InvalidArgument("Cannot call MultiGetEntity without keys");
3383 for (size_t i = 0; i < num_keys; ++i) {
3384 statuses[i] = s;
3385 }
3386
3387 return;
3388 }
3389
3390 if (!results) {
3391 const Status s = Status::InvalidArgument(
3392 "Cannot call MultiGetEntity without PinnableWideColumns objects");
3393 for (size_t i = 0; i < num_keys; ++i) {
3394 statuses[i] = s;
3395 }
3396
3397 return;
3398 }
3399
3400 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
3401 _read_options.io_activity != Env::IOActivity::kMultiGetEntity) {
3402 const Status s = Status::InvalidArgument(
3403 "Can only call MultiGetEntity with `ReadOptions::io_activity` set to "
3404 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGetEntity`");
3405 for (size_t i = 0; i < num_keys; ++i) {
3406 statuses[i] = s;
3407 }
3408 return;
3409 }
3410
3411 ReadOptions read_options(_read_options);
3412 if (read_options.io_activity == Env::IOActivity::kUnknown) {
3413 read_options.io_activity = Env::IOActivity::kMultiGetEntity;
3414 }
3415
3416 MultiGetCommon(read_options, column_family, num_keys, keys,
3417 /* values */ nullptr, results, /* timestamps */ nullptr,
3418 statuses, sorted_input);
3419}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetEntity() [2/3]

void ROCKSDB_NAMESPACE::DBImpl::MultiGetEntity ( const ReadOptions & options,
size_t num_keys,
ColumnFamilyHandle ** column_families,
const Slice * keys,
PinnableWideColumns * results,
Status * statuses,
bool sorted_input )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 3306 번째 라인에서 정의되었습니다.

3309 {
3310 assert(statuses);
3311
3312 if (!column_families) {
3313 const Status s = Status::InvalidArgument(
3314 "Cannot call MultiGetEntity without column families");
3315 for (size_t i = 0; i < num_keys; ++i) {
3316 statuses[i] = s;
3317 }
3318
3319 return;
3320 }
3321
3322 if (!keys) {
3323 const Status s =
3324 Status::InvalidArgument("Cannot call MultiGetEntity without keys");
3325 for (size_t i = 0; i < num_keys; ++i) {
3326 statuses[i] = s;
3327 }
3328
3329 return;
3330 }
3331
3332 if (!results) {
3333 const Status s = Status::InvalidArgument(
3334 "Cannot call MultiGetEntity without PinnableWideColumns objects");
3335 for (size_t i = 0; i < num_keys; ++i) {
3336 statuses[i] = s;
3337 }
3338
3339 return;
3340 }
3341
3342 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
3343 _read_options.io_activity != Env::IOActivity::kMultiGetEntity) {
3344 const Status s = Status::InvalidArgument(
3345 "Can only call MultiGetEntity with `ReadOptions::io_activity` set to "
3346 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGetEntity`");
3347 for (size_t i = 0; i < num_keys; ++i) {
3348 statuses[i] = s;
3349 }
3350
3351 return;
3352 }
3353
3354 ReadOptions read_options(_read_options);
3355 if (read_options.io_activity == Env::IOActivity::kUnknown) {
3356 read_options.io_activity = Env::IOActivity::kMultiGetEntity;
3357 }
3358
3359 MultiGetCommon(read_options, num_keys, column_families, keys,
3360 /* values */ nullptr, results, /* timestamps */ nullptr,
3361 statuses, sorted_input);
3362}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetEntity() [3/3]

void ROCKSDB_NAMESPACE::DBImpl::MultiGetEntity ( const ReadOptions & options,
size_t num_keys,
const Slice * keys,
PinnableAttributeGroups * results )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 3421 번째 라인에서 정의되었습니다.

3423 {
3424 assert(results);
3425
3426 if (!keys) {
3427 const Status s =
3428 Status::InvalidArgument("Cannot call MultiGetEntity without keys");
3429 for (size_t i = 0; i < num_keys; ++i) {
3430 for (size_t j = 0; j < results[i].size(); ++j) {
3431 results[i][j].SetStatus(s);
3432 }
3433 }
3434
3435 return;
3436 }
3437
3438 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
3439 _read_options.io_activity != Env::IOActivity::kMultiGetEntity) {
3440 const Status s = Status::InvalidArgument(
3441 "Can only call MultiGetEntity with `ReadOptions::io_activity` set to "
3442 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kMultiGetEntity`");
3443 for (size_t i = 0; i < num_keys; ++i) {
3444 for (size_t j = 0; j < results[i].size(); ++j) {
3445 results[i][j].SetStatus(s);
3446 }
3447 }
3448
3449 return;
3450 }
3451
3452 ReadOptions read_options(_read_options);
3453 if (read_options.io_activity == Env::IOActivity::kUnknown) {
3454 read_options.io_activity = Env::IOActivity::kMultiGetEntity;
3455 }
3456
3457 std::vector<ColumnFamilyHandle*> column_families;
3458 std::vector<Slice> all_keys;
3459 size_t total_count = 0;
3460
3461 for (size_t i = 0; i < num_keys; ++i) {
3462 for (size_t j = 0; j < results[i].size(); ++j) {
3463 // Adding the same key slice for different CFs
3464 all_keys.emplace_back(keys[i]);
3465 column_families.emplace_back(results[i][j].column_family());
3466 ++total_count;
3467 }
3468 }
3469
3470 std::vector<Status> statuses(total_count);
3471 std::vector<PinnableWideColumns> columns(total_count);
3472 MultiGetCommon(read_options, total_count, column_families.data(),
3473 all_keys.data(),
3474 /* values */ nullptr, columns.data(),
3475 /* timestamps */ nullptr, statuses.data(),
3476 /* sorted_input */ false);
3477
3478 // Set results
3479 size_t index = 0;
3480 for (size_t i = 0; i < num_keys; ++i) {
3481 for (size_t j = 0; j < results[i].size(); ++j) {
3482 results[i][j].Reset();
3483 results[i][j].SetStatus(std::move(statuses[index]));
3484 results[i][j].SetColumns(std::move(columns[index]));
3485 ++index;
3486 }
3487 }
3488}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetEntityWithCallback()

void ROCKSDB_NAMESPACE::DBImpl::MultiGetEntityWithCallback ( const ReadOptions & read_options,
ColumnFamilyHandle * column_family,
ReadCallback * callback,
autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > * sorted_keys )

db_impl.cc 파일의 3490 번째 라인에서 정의되었습니다.

3493 {
3494 assert(read_options.io_activity == Env::IOActivity::kMultiGetEntity);
3495
3496 MultiGetWithCallbackImpl(read_options, column_family, callback, sorted_keys);
3497}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetImpl()

Status ROCKSDB_NAMESPACE::DBImpl::MultiGetImpl ( const ReadOptions & read_options,
size_t start_key,
size_t num_keys,
autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > * sorted_keys,
SuperVersion * sv,
SequenceNumber snap_seqnum,
ReadCallback * callback )
private

db_impl.cc 파일의 3175 번째 라인에서 정의되었습니다.

3179 {
3181 StopWatch sw(immutable_db_options_.clock, stats_, DB_MULTIGET);
3182
3183 assert(sorted_keys);
3184 assert(start_key + num_keys <= sorted_keys->size());
3185 // Clear the timestamps for returning results so that we can distinguish
3186 // between tombstone or key that has never been written
3187 for (size_t i = start_key; i < start_key + num_keys; ++i) {
3188 KeyContext* kctx = (*sorted_keys)[i];
3189 if (kctx->timestamp) {
3190 kctx->timestamp->clear();
3191 }
3192 }
3193
3194 // For each of the given keys, apply the entire "get" process as follows:
3195 // First look in the memtable, then in the immutable memtable (if any).
3196 // s is both in/out. When in, s could either be OK or MergeInProgress.
3197 // merge_operands will contain the sequence of merges in the latter case.
3198 size_t keys_left = num_keys;
3199 Status s;
3200 uint64_t curr_value_size = 0;
3201 while (keys_left) {
3202 if (read_options.deadline.count() &&
3204 static_cast<uint64_t>(read_options.deadline.count())) {
3205 s = Status::TimedOut();
3206 break;
3207 }
3208
3209 size_t batch_size = (keys_left > MultiGetContext::MAX_BATCH_SIZE)
3210 ? MultiGetContext::MAX_BATCH_SIZE
3211 : keys_left;
3212 MultiGetContext ctx(sorted_keys, start_key + num_keys - keys_left,
3213 batch_size, snapshot, read_options, GetFileSystem(),
3214 stats_);
3215 MultiGetRange range = ctx.GetMultiGetRange();
3216 range.AddValueSize(curr_value_size);
3217 bool lookup_current = true;
3218
3219 keys_left -= batch_size;
3220 for (auto mget_iter = range.begin(); mget_iter != range.end();
3221 ++mget_iter) {
3222 mget_iter->merge_context.Clear();
3223 *mget_iter->s = Status::OK();
3224 }
3225
3226 bool skip_memtable =
3227 (read_options.read_tier == kPersistedTier &&
3228 has_unpersisted_data_.load(std::memory_order_relaxed));
3229 if (!skip_memtable) {
3230 super_version->mem->MultiGet(read_options, &range, callback,
3231 false /* immutable_memtable */);
3232 if (!range.empty()) {
3233 super_version->imm->MultiGet(read_options, &range, callback);
3234 }
3235 if (!range.empty()) {
3236 uint64_t left = range.KeysLeft();
3237 RecordTick(stats_, MEMTABLE_MISS, left);
3238 } else {
3239 lookup_current = false;
3240 }
3241 }
3242 if (lookup_current) {
3243 PERF_TIMER_GUARD(get_from_output_files_time);
3244 super_version->current->MultiGet(read_options, &range, callback);
3245 }
3246 curr_value_size = range.GetValueSize();
3247 if (curr_value_size > read_options.value_size_soft_limit) {
3248 s = Status::Aborted();
3249 break;
3250 }
3251
3252 // This could be a long-running operation
3253 bool aborted = ROCKSDB_THREAD_YIELD_CHECK_ABORT();
3254 if (aborted) {
3255 s = Status::Aborted("Query abort.");
3256 break;
3257 }
3258 }
3259
3260 // Post processing (decrement reference counts and record statistics)
3261 PERF_TIMER_GUARD(get_post_process_time);
3262 size_t num_found = 0;
3263 uint64_t bytes_read = 0;
3264 for (size_t i = start_key; i < start_key + num_keys - keys_left; ++i) {
3265 KeyContext* key = (*sorted_keys)[i];
3266 assert(key);
3267 assert(key->s);
3268
3269 if (key->s->ok()) {
3270 const auto& merge_threshold = read_options.merge_operand_count_threshold;
3271 if (merge_threshold.has_value() &&
3272 key->merge_context.GetNumOperands() > merge_threshold) {
3273 *(key->s) = Status::OkMergeOperandThresholdExceeded();
3274 }
3275
3276 if (key->value) {
3277 bytes_read += key->value->size();
3278 } else {
3279 assert(key->columns);
3280 bytes_read += key->columns->serialized_size();
3281 }
3282
3283 num_found++;
3284 }
3285 }
3286 if (keys_left) {
3287 assert(s.IsTimedOut() || s.IsAborted());
3288 for (size_t i = start_key + num_keys - keys_left; i < start_key + num_keys;
3289 ++i) {
3290 KeyContext* key = (*sorted_keys)[i];
3291 *key->s = s;
3292 }
3293 }
3294
3295 RecordTick(stats_, NUMBER_MULTIGET_CALLS);
3296 RecordTick(stats_, NUMBER_MULTIGET_KEYS_READ, num_keys);
3297 RecordTick(stats_, NUMBER_MULTIGET_KEYS_FOUND, num_found);
3298 RecordTick(stats_, NUMBER_MULTIGET_BYTES_READ, bytes_read);
3299 RecordInHistogram(stats_, BYTES_PER_MULTIGET, bytes_read);
3300 PERF_COUNTER_ADD(multiget_read_bytes, bytes_read);
3301 PERF_TIMER_STOP(get_post_process_time);
3302
3303 return s;
3304}
FileSystem * GetFileSystem() const override
Definition db_impl.cc:4475
MultiGetContext::Range MultiGetRange
Definition memtable.h:79
#define ROCKSDB_THREAD_YIELD_CHECK_ABORT()
Definition port.h:32
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetWithCallback()

void ROCKSDB_NAMESPACE::DBImpl::MultiGetWithCallback ( const ReadOptions & _read_options,
ColumnFamilyHandle * column_family,
ReadCallback * callback,
autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > * sorted_keys )

db_impl.cc 파일의 3088 번째 라인에서 정의되었습니다.

3091 {
3092 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
3093 _read_options.io_activity != Env::IOActivity::kMultiGet) {
3094 assert(false);
3095 return;
3096 }
3097
3098 ReadOptions read_options(_read_options);
3099 if (read_options.io_activity == Env::IOActivity::kUnknown) {
3100 read_options.io_activity = Env::IOActivity::kMultiGet;
3101 }
3102 MultiGetWithCallbackImpl(read_options, column_family, callback, sorted_keys);
3103}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ MultiGetWithCallbackImpl()

void ROCKSDB_NAMESPACE::DBImpl::MultiGetWithCallbackImpl ( const ReadOptions & read_options,
ColumnFamilyHandle * column_family,
ReadCallback * callback,
autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > * sorted_keys )
private

db_impl.cc 파일의 3105 번째 라인에서 정의되었습니다.

3108 {
3109 std::array<ColumnFamilySuperVersionPair, 1> cf_sv_pairs;
3110 cf_sv_pairs[0] = ColumnFamilySuperVersionPair(column_family, nullptr);
3111 size_t num_keys = sorted_keys->size();
3112 SequenceNumber consistent_seqnum = kMaxSequenceNumber;
3113 bool sv_from_thread_local = false;
3114 Status s = MultiCFSnapshot<std::array<ColumnFamilySuperVersionPair, 1>>(
3115 read_options, callback,
3116 [](std::array<ColumnFamilySuperVersionPair, 1>::iterator& cf_iter) {
3117 return &(*cf_iter);
3118 },
3119 &cf_sv_pairs,
3120 /* extra_sv_ref */ false, &consistent_seqnum, &sv_from_thread_local);
3121 if (!s.ok()) {
3122 return;
3123 }
3124#ifndef NDEBUG
3125 assert(sv_from_thread_local);
3126#else
3127 // Silence unused variable warning
3128 (void)sv_from_thread_local;
3129#endif // NDEBUG
3130
3131 if (callback && read_options.snapshot == nullptr) {
3132 // The unprep_seqs are not published for write unprepared, so it could be
3133 // that max_visible_seq is larger. Seek to the std::max of the two.
3134 // However, we still want our callback to contain the actual snapshot so
3135 // that it can do the correct visibility filtering.
3136 callback->Refresh(consistent_seqnum);
3137
3138 // Internally, WriteUnpreparedTxnReadCallback::Refresh would set
3139 // max_visible_seq = max(max_visible_seq, snapshot)
3140 //
3141 // Currently, the commented out assert is broken by
3142 // InvalidSnapshotReadCallback, but if write unprepared recovery followed
3143 // the regular transaction flow, then this special read callback would not
3144 // be needed.
3145 //
3146 // assert(callback->max_visible_seq() >= snapshot);
3147 consistent_seqnum = callback->max_visible_seq();
3148 }
3149
3150 GetWithTimestampReadCallback timestamp_read_callback(0);
3151 ReadCallback* read_callback = callback;
3152 if (read_options.timestamp && read_options.timestamp->size() > 0) {
3153 assert(!read_callback); // timestamp with callback is not supported
3154 timestamp_read_callback.Refresh(consistent_seqnum);
3155 read_callback = &timestamp_read_callback;
3156 }
3157
3158 s = MultiGetImpl(read_options, 0, num_keys, sorted_keys,
3159 cf_sv_pairs[0].super_version, consistent_seqnum,
3160 read_callback);
3161 assert(s.ok() || s.IsTimedOut() || s.IsAborted());
3162 ReturnAndCleanupSuperVersion(cf_sv_pairs[0].cfd,
3163 cf_sv_pairs[0].super_version);
3164}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ mutex()

InstrumentedMutex * ROCKSDB_NAMESPACE::DBImpl::mutex ( ) const
inline

db_impl.h 파일의 1075 번째 라인에서 정의되었습니다.

1075{ return &mutex_; }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewAttributeGroupIterator()

std::unique_ptr< AttributeGroupIterator > ROCKSDB_NAMESPACE::DBImpl::NewAttributeGroupIterator ( const ReadOptions & options,
const std::vector< ColumnFamilyHandle * > & column_families )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 3998 번째 라인에서 정의되었습니다.

4000 {
4001 return NewMultiCfIterator<AttributeGroupIterator, AttributeGroupIteratorImpl>(
4002 _read_options, column_families,
4003 [](const Status& s) { return NewAttributeGroupErrorIterator(s); });
4004}
std::unique_ptr< AttributeGroupIterator > NewAttributeGroupErrorIterator(const Status &status)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewCoalescingIterator()

std::unique_ptr< Iterator > ROCKSDB_NAMESPACE::DBImpl::NewCoalescingIterator ( const ReadOptions & options,
const std::vector< ColumnFamilyHandle * > & column_families )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 3989 번째 라인에서 정의되었습니다.

3991 {
3992 return NewMultiCfIterator<Iterator, CoalescingIterator>(
3993 _read_options, column_families, [](const Status& s) {
3994 return std::unique_ptr<Iterator>(NewErrorIterator(s));
3995 });
3996}
Iterator * NewErrorIterator(const Status &status)
Definition iterator.cc:90
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewDB()

Status ROCKSDB_NAMESPACE::DBImpl::NewDB ( std::vector< std::string > * new_filenames)

db_impl_open.cc 파일의 300 번째 라인에서 정의되었습니다.

300 {
301 VersionEdit new_db_edit;
302 const WriteOptions write_options(Env::IOActivity::kDBOpen);
303 Status s = SetupDBId(write_options, /*read_only=*/false, /*is_new_db=*/true,
304 /*is_retry=*/false, &new_db_edit);
305 if (!s.ok()) {
306 return s;
307 }
308 new_db_edit.SetLogNumber(0);
309 new_db_edit.SetNextFile(2);
310 new_db_edit.SetLastSequence(0);
311
312 ROCKS_LOG_INFO(immutable_db_options_.info_log, "Creating manifest 1 \n");
313 const std::string manifest = DescriptorFileName(dbname_, 1);
314 {
315 if (fs_->FileExists(manifest, IOOptions(), nullptr).ok()) {
316 fs_->DeleteFile(manifest, IOOptions(), nullptr).PermitUncheckedError();
317 }
318 std::unique_ptr<FSWritableFile> file;
319 FileOptions file_options = fs_->OptimizeForManifestWrite(file_options_);
320 // DB option takes precedence when not kUnknown
322 Temperature::kUnknown) {
323 file_options.temperature =
325 }
326 s = NewWritableFile(fs_.get(), manifest, &file, file_options);
327 if (!s.ok()) {
328 return s;
329 }
331 file->SetPreallocationBlockSize(
333 std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
334 std::move(file), manifest, file_options, immutable_db_options_.clock,
335 io_tracer_, nullptr /* stats */,
336 Histograms::HISTOGRAM_ENUM_MAX /* hist_type */,
338 tmp_set.Contains(FileType::kDescriptorFile),
339 tmp_set.Contains(FileType::kDescriptorFile)));
340 log::Writer log(std::move(file_writer), 0, false);
341 std::string record;
342 new_db_edit.EncodeTo(&record);
343 s = log.AddRecord(write_options, record);
344 if (s.ok()) {
345 s = SyncManifest(&immutable_db_options_, write_options, log.file());
346 }
347 }
348 if (s.ok()) {
349 // Make "CURRENT" file that points to the new manifest file.
350 s = SetCurrentFile(write_options, fs_.get(), dbname_, 1,
353 if (new_filenames) {
354 new_filenames->emplace_back(
355 manifest.substr(manifest.find_last_of("/\\") + 1));
356 }
357 } else {
358 fs_->DeleteFile(manifest, IOOptions(), nullptr).PermitUncheckedError();
359 }
360 return s;
361}
Status SetupDBId(const WriteOptions &write_options, bool read_only, bool is_new_db, bool is_retry, VersionEdit *version_edit)
IOStatus SetCurrentFile(const WriteOptions &write_options, FileSystem *fs, const std::string &dbname, uint64_t descriptor_number, Temperature temp, FSDirectory *dir_contains_current_file)
Definition filename.cc:389
IOStatus SyncManifest(const ImmutableDBOptions *db_options, const WriteOptions &write_options, WritableFileWriter *file)
Definition filename.cc:482
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewDefaultReplayer()

Status ROCKSDB_NAMESPACE::DBImpl::NewDefaultReplayer ( const std::vector< ColumnFamilyHandle * > & handles,
std::unique_ptr< TraceReader > && reader,
std::unique_ptr< Replayer > * replayer )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6680 번째 라인에서 정의되었습니다.

6683 {
6684 replayer->reset(new ReplayerImpl(this, handles, std::move(reader)));
6685 return Status::OK();
6686}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewInternalIterator() [1/2]

InternalIterator * ROCKSDB_NAMESPACE::DBImpl::NewInternalIterator ( const ReadOptions & read_options,
Arena * arena,
SequenceNumber sequence,
ColumnFamilyHandle * column_family = nullptr,
bool allow_unprepared_value = false )

db_impl.cc 파일의 1934 번째 라인에서 정의되었습니다.

1938 {
1939 ColumnFamilyData* cfd;
1940 if (column_family == nullptr) {
1941 cfd = default_cf_handle_->cfd();
1942 } else {
1943 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1944 cfd = cfh->cfd();
1945 }
1946
1947 mutex_.Lock();
1948 SuperVersion* super_version = cfd->GetSuperVersion()->Ref();
1949 mutex_.Unlock();
1950 return NewInternalIterator(read_options, cfd, super_version, arena, sequence,
1951 allow_unprepared_value);
1952}
InternalIterator * NewInternalIterator(const ReadOptions &read_options, Arena *arena, SequenceNumber sequence, ColumnFamilyHandle *column_family=nullptr, bool allow_unprepared_value=false)
Definition db_impl.cc:1934
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewInternalIterator() [2/2]

InternalIterator * ROCKSDB_NAMESPACE::DBImpl::NewInternalIterator ( const ReadOptions & read_options,
ColumnFamilyData * cfd,
SuperVersion * super_version,
Arena * arena,
SequenceNumber sequence,
bool allow_unprepared_value,
ArenaWrappedDBIter * db_iter = nullptr )

db_impl.cc 파일의 2083 번째 라인에서 정의되었습니다.

2086 {
2087 InternalIterator* internal_iter;
2088 assert(arena != nullptr);
2089 auto prefix_extractor =
2090 super_version->mutable_cf_options.prefix_extractor.get();
2091 // Need to create internal iterator from the arena.
2092 MergeIteratorBuilder merge_iter_builder(
2093 &cfd->internal_comparator(), arena,
2094 // FIXME? It's not clear what interpretation of prefix seek is needed
2095 // here, and no unit test cares about the value provided here.
2096 !read_options.total_order_seek && prefix_extractor != nullptr,
2097 read_options.iterate_upper_bound);
2098 // Collect iterator for mutable memtable
2099 auto mem_iter = super_version->mem->NewIterator(
2100 read_options, super_version->GetSeqnoToTimeMapping(), arena,
2101 super_version->mutable_cf_options.prefix_extractor.get(),
2102 /*for_flush=*/false);
2103 Status s;
2104 if (!read_options.ignore_range_deletions) {
2105 std::unique_ptr<TruncatedRangeDelIterator> mem_tombstone_iter;
2106 auto range_del_iter = super_version->mem->NewRangeTombstoneIterator(
2107 read_options, sequence, false /* immutable_memtable */);
2108 if (range_del_iter == nullptr || range_del_iter->empty()) {
2109 delete range_del_iter;
2110 } else {
2111 mem_tombstone_iter = std::make_unique<TruncatedRangeDelIterator>(
2112 std::unique_ptr<FragmentedRangeTombstoneIterator>(range_del_iter),
2113 &cfd->ioptions()->internal_comparator, nullptr /* smallest */,
2114 nullptr /* largest */);
2115 }
2116 merge_iter_builder.AddPointAndTombstoneIterator(
2117 mem_iter, std::move(mem_tombstone_iter));
2118 } else {
2119 merge_iter_builder.AddIterator(mem_iter);
2120 }
2121
2122 // Collect all needed child iterators for immutable memtables
2123 if (s.ok()) {
2124 super_version->imm->AddIterators(
2125 read_options, super_version->GetSeqnoToTimeMapping(),
2126 super_version->mutable_cf_options.prefix_extractor.get(),
2127 &merge_iter_builder, !read_options.ignore_range_deletions);
2128 }
2129 TEST_SYNC_POINT_CALLBACK("DBImpl::NewInternalIterator:StatusCallback", &s);
2130 if (s.ok()) {
2131 // Collect iterators for files in L0 - Ln
2132 if (read_options.read_tier != kMemtableTier) {
2133 super_version->current->AddIterators(read_options, file_options_,
2134 &merge_iter_builder,
2135 allow_unprepared_value);
2136 }
2137 internal_iter = merge_iter_builder.Finish(
2138 read_options.ignore_range_deletions ? nullptr : db_iter);
2139 SuperVersionHandle* cleanup = new SuperVersionHandle(
2140 this, &mutex_, super_version,
2141 read_options.background_purge_on_iterator_cleanup ||
2143 internal_iter->RegisterCleanup(CleanupSuperVersionHandle, cleanup, nullptr);
2144
2145 return internal_iter;
2146 } else {
2147 CleanupSuperVersion(super_version);
2148 }
2149 return NewErrorInternalIterator<Slice>(s, arena);
2150}
InternalIteratorBase< Slice > InternalIterator
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ NewIterator() [1/2]

Iterator * ROCKSDB_NAMESPACE::DBImpl::NewIterator ( const ReadOptions & _read_options,
ColumnFamilyHandle * column_family )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 3837 번째 라인에서 정의되었습니다.

3838 {
3839 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
3840 _read_options.io_activity != Env::IOActivity::kDBIterator) {
3841 return NewErrorIterator(Status::InvalidArgument(
3842 "Can only call NewIterator with `ReadOptions::io_activity` is "
3843 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kDBIterator`"));
3844 }
3845 ReadOptions read_options(_read_options);
3846 if (read_options.io_activity == Env::IOActivity::kUnknown) {
3847 read_options.io_activity = Env::IOActivity::kDBIterator;
3848 }
3849
3850 if (read_options.managed) {
3851 return NewErrorIterator(
3852 Status::NotSupported("Managed iterator is not supported anymore."));
3853 }
3854 Iterator* result = nullptr;
3855 if (read_options.read_tier == kPersistedTier) {
3856 return NewErrorIterator(Status::NotSupported(
3857 "ReadTier::kPersistedData is not yet supported in iterators."));
3858 }
3859 assert(column_family);
3860
3861 if (read_options.timestamp) {
3862 const Status s =
3863 FailIfTsMismatchCf(column_family, *(read_options.timestamp));
3864 if (!s.ok()) {
3865 return NewErrorIterator(s);
3866 }
3867 } else {
3868 const Status s = FailIfCfHasTs(column_family);
3869 if (!s.ok()) {
3870 return NewErrorIterator(s);
3871 }
3872 }
3873
3874 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
3875 assert(cfh != nullptr);
3876 ColumnFamilyData* cfd = cfh->cfd();
3877 assert(cfd != nullptr);
3878 SuperVersion* sv = cfd->GetReferencedSuperVersion(this);
3879 if (read_options.timestamp && read_options.timestamp->size() > 0) {
3880 const Status s =
3881 FailIfReadCollapsedHistory(cfd, sv, *(read_options.timestamp));
3882 if (!s.ok()) {
3884 return NewErrorIterator(s);
3885 }
3886 }
3887 if (read_options.tailing) {
3888 read_options.total_order_seek |=
3890
3891 auto iter = new ForwardIterator(this, read_options, cfd, sv,
3892 /* allow_unprepared_value */ true);
3893 result = NewDBIterator(
3894 env_, read_options, *cfd->ioptions(), sv->mutable_cf_options,
3895 cfd->user_comparator(), iter, sv->current, kMaxSequenceNumber,
3896 sv->mutable_cf_options.max_sequential_skip_in_iterations,
3897 nullptr /* read_callback */, cfh);
3898 } else {
3899 // Note: no need to consider the special case of
3900 // last_seq_same_as_publish_seq_==false since NewIterator is overridden in
3901 // WritePreparedTxnDB
3902 result = NewIteratorImpl(read_options, cfh, sv,
3903 (read_options.snapshot != nullptr)
3904 ? read_options.snapshot->GetSequenceNumber()
3905 : kMaxSequenceNumber,
3906 nullptr /* read_callback */);
3907 }
3908 return result;
3909}
ArenaWrappedDBIter * NewIteratorImpl(const ReadOptions &options, ColumnFamilyHandleImpl *cfh, SuperVersion *sv, SequenceNumber snapshot, ReadCallback *read_callback, bool expose_blob_index=false, bool allow_refresh=true)
Definition db_impl.cc:3911
friend class ForwardIterator
Definition db_impl.h:1716
Iterator * NewDBIterator(Env *env, const ReadOptions &read_options, const ImmutableOptions &ioptions, const MutableCFOptions &mutable_cf_options, const Comparator *user_key_comparator, InternalIterator *internal_iter, const Version *version, const SequenceNumber &sequence, uint64_t max_sequential_skip_in_iterations, ReadCallback *read_callback, ColumnFamilyHandleImpl *cfh, bool expose_blob_index)
Definition db_iter.cc:1794
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewIterator() [2/2]

virtual Iterator * ROCKSDB_NAMESPACE::DB::NewIterator ( const ReadOptions & options)
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 1000 번째 라인에서 정의되었습니다.

1000 {
1001 return NewIterator(options, DefaultColumnFamily());
1002 }
Iterator * NewIterator(const ReadOptions &_read_options, ColumnFamilyHandle *column_family) override
Definition db_impl.cc:3837

◆ NewIteratorImpl()

ArenaWrappedDBIter * ROCKSDB_NAMESPACE::DBImpl::NewIteratorImpl ( const ReadOptions & options,
ColumnFamilyHandleImpl * cfh,
SuperVersion * sv,
SequenceNumber snapshot,
ReadCallback * read_callback,
bool expose_blob_index = false,
bool allow_refresh = true )

db_impl.cc 파일의 3911 번째 라인에서 정의되었습니다.

3914 {
3915 TEST_SYNC_POINT("DBImpl::NewIterator:1");
3916 TEST_SYNC_POINT("DBImpl::NewIterator:2");
3917
3918 if (snapshot == kMaxSequenceNumber) {
3919 // Note that the snapshot is assigned AFTER referencing the super
3920 // version because otherwise a flush happening in between may compact away
3921 // data for the snapshot, so the reader would see neither data that was be
3922 // visible to the snapshot before compaction nor the newer data inserted
3923 // afterwards.
3924 // Note that the super version might not contain all the data available
3925 // to this snapshot, but in that case it can see all the data in the
3926 // super version, which is a valid consistent state after the user
3927 // calls NewIterator().
3928 snapshot = versions_->LastSequence();
3929 TEST_SYNC_POINT("DBImpl::NewIterator:3");
3930 TEST_SYNC_POINT("DBImpl::NewIterator:4");
3931 }
3932
3933 // Try to generate a DB iterator tree in continuous memory area to be
3934 // cache friendly. Here is an example of result:
3935 // +-------------------------------+
3936 // | |
3937 // | ArenaWrappedDBIter |
3938 // | + |
3939 // | +---> Inner Iterator ------------+
3940 // | | | |
3941 // | | +-- -- -- -- -- -- -- --+ |
3942 // | +--- | Arena | |
3943 // | | | |
3944 // | Allocated Memory: | |
3945 // | | +-------------------+ |
3946 // | | | DBIter | <---+
3947 // | | + |
3948 // | | | +-> iter_ ------------+
3949 // | | | | |
3950 // | | +-------------------+ |
3951 // | | | MergingIterator | <---+
3952 // | | + |
3953 // | | | +->child iter1 ------------+
3954 // | | | | | |
3955 // | | +->child iter2 ----------+ |
3956 // | | | | | | |
3957 // | | | +->child iter3 --------+ | |
3958 // | | | | | |
3959 // | | +-------------------+ | | |
3960 // | | | Iterator1 | <--------+
3961 // | | +-------------------+ | |
3962 // | | | Iterator2 | <------+
3963 // | | +-------------------+ |
3964 // | | | Iterator3 | <----+
3965 // | | +-------------------+
3966 // | | |
3967 // +-------+-----------------------+
3968 //
3969 // ArenaWrappedDBIter inlines an arena area where all the iterators in
3970 // the iterator tree are allocated in the order of being accessed when
3971 // querying.
3972 // Laying out the iterators in the order of being accessed makes it more
3973 // likely that any iterator pointer is close to the iterator it points to so
3974 // that they are likely to be in the same cache line and/or page.
3975 ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
3976 env_, read_options, *cfh->cfd()->ioptions(), sv->mutable_cf_options,
3977 sv->current, snapshot,
3978 sv->mutable_cf_options.max_sequential_skip_in_iterations,
3979 sv->version_number, read_callback, cfh, expose_blob_index, allow_refresh);
3980
3981 InternalIterator* internal_iter = NewInternalIterator(
3982 db_iter->GetReadOptions(), cfh->cfd(), sv, db_iter->GetArena(), snapshot,
3983 /* allow_unprepared_value */ true, db_iter);
3984 db_iter->SetIterUnderDBIter(internal_iter);
3985
3986 return db_iter;
3987}
ArenaWrappedDBIter * NewArenaWrappedDbIterator(Env *env, const ReadOptions &read_options, const ImmutableOptions &ioptions, const MutableCFOptions &mutable_cf_options, const Version *version, const SequenceNumber &sequence, uint64_t max_sequential_skip_in_iterations, uint64_t version_number, ReadCallback *read_callback, ColumnFamilyHandleImpl *cfh, bool expose_blob_index, bool allow_refresh)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewIterators()

Status ROCKSDB_NAMESPACE::DBImpl::NewIterators ( const ReadOptions & _read_options,
const std::vector< ColumnFamilyHandle * > & column_families,
std::vector< Iterator * > * iterators )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 4045 번째 라인에서 정의되었습니다.

4048 {
4049 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
4050 _read_options.io_activity != Env::IOActivity::kDBIterator) {
4051 return Status::InvalidArgument(
4052 "Can only call NewIterators with `ReadOptions::io_activity` is "
4053 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kDBIterator`");
4054 }
4055 ReadOptions read_options(_read_options);
4056 if (read_options.io_activity == Env::IOActivity::kUnknown) {
4057 read_options.io_activity = Env::IOActivity::kDBIterator;
4058 }
4059 if (read_options.managed) {
4060 return Status::NotSupported("Managed iterator is not supported anymore.");
4061 }
4062 if (read_options.read_tier == kPersistedTier) {
4063 return Status::NotSupported(
4064 "ReadTier::kPersistedData is not yet supported in iterators.");
4065 }
4066
4067 autovector<ColumnFamilySuperVersionPair, MultiGetContext::MAX_BATCH_SIZE>
4068 cf_sv_pairs;
4069
4070 Status s;
4071 for (auto* cf : column_families) {
4072 assert(cf);
4073 if (read_options.timestamp) {
4074 s = FailIfTsMismatchCf(cf, *(read_options.timestamp));
4075 } else {
4076 s = FailIfCfHasTs(cf);
4077 }
4078 if (!s.ok()) {
4079 return s;
4080 }
4081 cf_sv_pairs.emplace_back(cf, nullptr);
4082 }
4083 iterators->clear();
4084 iterators->reserve(column_families.size());
4085
4086 SequenceNumber consistent_seqnum = kMaxSequenceNumber;
4087 bool sv_from_thread_local = false;
4088 s = MultiCFSnapshot<autovector<ColumnFamilySuperVersionPair,
4089 MultiGetContext::MAX_BATCH_SIZE>>(
4090 read_options, nullptr /* read_callback*/,
4091 [](autovector<ColumnFamilySuperVersionPair,
4092 MultiGetContext::MAX_BATCH_SIZE>::iterator& cf_iter) {
4093 return &(*cf_iter);
4094 },
4095 &cf_sv_pairs,
4096 /* extra_sv_ref */ true, &consistent_seqnum, &sv_from_thread_local);
4097 if (!s.ok()) {
4098 return s;
4099 }
4100
4101 assert(cf_sv_pairs.size() == column_families.size());
4102 if (read_options.tailing) {
4103 read_options.total_order_seek |=
4105
4106 for (const auto& cf_sv_pair : cf_sv_pairs) {
4107 auto iter = new ForwardIterator(this, read_options, cf_sv_pair.cfd,
4108 cf_sv_pair.super_version,
4109 /* allow_unprepared_value */ true);
4110 iterators->push_back(
4111 NewDBIterator(env_, read_options, *cf_sv_pair.cfd->ioptions(),
4112 cf_sv_pair.super_version->mutable_cf_options,
4113 cf_sv_pair.cfd->user_comparator(), iter,
4114 cf_sv_pair.super_version->current, kMaxSequenceNumber,
4115 cf_sv_pair.super_version->mutable_cf_options
4116 .max_sequential_skip_in_iterations,
4117 nullptr /*read_callback*/, cf_sv_pair.cfh));
4118 }
4119 } else {
4120 for (const auto& cf_sv_pair : cf_sv_pairs) {
4121 iterators->push_back(NewIteratorImpl(
4122 read_options, cf_sv_pair.cfh, cf_sv_pair.super_version,
4123 consistent_seqnum, nullptr /*read_callback*/));
4124 }
4125 }
4126 return Status::OK();
4127}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewMultiCfIterator()

template<typename IterType, typename ImplType, typename ErrorIteratorFuncType>
std::unique_ptr< IterType > ROCKSDB_NAMESPACE::DBImpl::NewMultiCfIterator ( const ReadOptions & _read_options,
const std::vector< ColumnFamilyHandle * > & column_families,
ErrorIteratorFuncType error_iterator_func )
private

db_impl.cc 파일의 4007 번째 라인에서 정의되었습니다.

4010 {
4011 if (column_families.size() == 0) {
4012 return error_iterator_func(
4013 Status::InvalidArgument("No Column Family was provided"));
4014 }
4015 const Comparator* first_comparator = column_families[0]->GetComparator();
4016 for (size_t i = 1; i < column_families.size(); ++i) {
4017 const Comparator* cf_comparator = column_families[i]->GetComparator();
4018 if (first_comparator != cf_comparator &&
4019 first_comparator->GetId().compare(cf_comparator->GetId()) != 0) {
4020 return error_iterator_func(Status::InvalidArgument(
4021 "Different comparators are being used across CFs"));
4022 }
4023 }
4024
4025 std::vector<Iterator*> child_iterators;
4026 Status s = NewIterators(_read_options, column_families, &child_iterators);
4027 if (!s.ok()) {
4028 return error_iterator_func(s);
4029 }
4030
4031 assert(column_families.size() == child_iterators.size());
4032
4033 std::vector<std::pair<ColumnFamilyHandle*, std::unique_ptr<Iterator>>>
4034 cfh_iter_pairs;
4035 cfh_iter_pairs.reserve(column_families.size());
4036 for (size_t i = 0; i < column_families.size(); ++i) {
4037 cfh_iter_pairs.emplace_back(column_families[i], child_iterators[i]);
4038 }
4039
4040 return std::make_unique<ImplType>(_read_options,
4041 column_families[0]->GetComparator(),
4042 std::move(cfh_iter_pairs));
4043}
Status NewIterators(const ReadOptions &_read_options, const std::vector< ColumnFamilyHandle * > &column_families, std::vector< Iterator * > *iterators) override
Definition db_impl.cc:4045
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NewThreadStatusCfInfo()

void ROCKSDB_NAMESPACE::DBImpl::NewThreadStatusCfInfo ( ColumnFamilyData * cfd) const
protected

db_impl.cc 파일의 5699 번째 라인에서 정의되었습니다.

5699{}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnCompactionBegin()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnCompactionBegin ( ColumnFamilyData * cfd,
Compaction * c,
const Status & st,
const CompactionJobStats & job_stats,
int job_id )
protected

db_impl_compaction_flush.cc 파일의 1687 번째 라인에서 정의되었습니다.

1690 {
1691 if (immutable_db_options_.listeners.empty()) {
1692 return;
1693 }
1694 mutex_.AssertHeld();
1695 if (shutting_down_.load(std::memory_order_acquire)) {
1696 return;
1697 }
1698 if (c->is_manual_compaction() &&
1699 manual_compaction_paused_.load(std::memory_order_acquire) > 0) {
1700 return;
1701 }
1702
1703 c->SetNotifyOnCompactionCompleted();
1704 // release lock while notifying events
1705 mutex_.Unlock();
1706 TEST_SYNC_POINT("DBImpl::NotifyOnCompactionBegin::UnlockMutex");
1707 {
1708 CompactionJobInfo info{};
1709 BuildCompactionJobInfo(cfd, c, st, job_stats, job_id, &info);
1710 for (const auto& listener : immutable_db_options_.listeners) {
1711 listener->OnCompactionBegin(this, info);
1712 }
1713 info.status.PermitUncheckedError();
1714 }
1715 mutex_.Lock();
1716}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnCompactionCompleted()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnCompactionCompleted ( ColumnFamilyData * cfd,
Compaction * c,
const Status & st,
const CompactionJobStats & job_stats,
int job_id )
protected

db_impl_compaction_flush.cc 파일의 1718 번째 라인에서 정의되었습니다.

1720 {
1721 if (immutable_db_options_.listeners.size() == 0U) {
1722 return;
1723 }
1724 mutex_.AssertHeld();
1725 if (shutting_down_.load(std::memory_order_acquire)) {
1726 return;
1727 }
1728
1729 if (c->ShouldNotifyOnCompactionCompleted() == false) {
1730 return;
1731 }
1732
1733 // release lock while notifying events
1734 mutex_.Unlock();
1735 TEST_SYNC_POINT("DBImpl::NotifyOnCompactionCompleted::UnlockMutex");
1736 {
1737 CompactionJobInfo info{};
1738 BuildCompactionJobInfo(cfd, c, st, compaction_job_stats, job_id, &info);
1739 for (const auto& listener : immutable_db_options_.listeners) {
1740 listener->OnCompactionCompleted(this, info);
1741 }
1742 }
1743 mutex_.Lock();
1744 // no need to signal bg_cv_ as it will be signaled at the end of the
1745 // flush process.
1746}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnExternalFileIngested()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnExternalFileIngested ( ColumnFamilyData * cfd,
const ExternalSstFileIngestionJob & ingestion_job )
protected

db_impl.cc 파일의 6641 번째 라인에서 정의되었습니다.

6642 {
6643 if (immutable_db_options_.listeners.empty()) {
6644 return;
6645 }
6646
6647 for (const IngestedFileInfo& f : ingestion_job.files_to_ingest()) {
6648 ExternalFileIngestionInfo info;
6649 info.cf_name = cfd->GetName();
6650 info.external_file_path = f.external_file_path;
6651 info.internal_file_path = f.internal_file_path;
6652 info.global_seqno = f.assigned_seqno;
6653 info.table_properties = f.table_properties;
6654 for (const auto& listener : immutable_db_options_.listeners) {
6655 listener->OnExternalFileIngested(this, info);
6656 }
6657 }
6658}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnFlushBegin()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnFlushBegin ( ColumnFamilyData * cfd,
FileMetaData * file_meta,
const MutableCFOptions & mutable_cf_options,
int job_id,
FlushReason flush_reason )
protected

db_impl_compaction_flush.cc 파일의 885 번째 라인에서 정의되었습니다.

887 {
888 if (immutable_db_options_.listeners.size() == 0U) {
889 return;
890 }
891 mutex_.AssertHeld();
892 if (shutting_down_.load(std::memory_order_acquire)) {
893 return;
894 }
895 bool triggered_writes_slowdown =
896 (cfd->current()->storage_info()->NumLevelFiles(0) >=
897 mutable_cf_options.level0_slowdown_writes_trigger);
898 bool triggered_writes_stop =
899 (cfd->current()->storage_info()->NumLevelFiles(0) >=
900 mutable_cf_options.level0_stop_writes_trigger);
901 // release lock while notifying events
902 mutex_.Unlock();
903 {
904 FlushJobInfo info{};
905 info.cf_id = cfd->GetID();
906 info.cf_name = cfd->GetName();
907 // TODO(yhchiang): make db_paths dynamic in case flush does not
908 // go to L0 in the future.
909 const uint64_t file_number = file_meta->fd.GetNumber();
910 info.file_path =
911 MakeTableFileName(cfd->ioptions()->cf_paths[0].path, file_number);
912 info.file_number = file_number;
913 info.thread_id = env_->GetThreadID();
914 info.job_id = job_id;
915 info.triggered_writes_slowdown = triggered_writes_slowdown;
916 info.triggered_writes_stop = triggered_writes_stop;
917 info.smallest_seqno = file_meta->fd.smallest_seqno;
918 info.largest_seqno = file_meta->fd.largest_seqno;
919 info.flush_reason = flush_reason;
920 for (const auto& listener : immutable_db_options_.listeners) {
921 listener->OnFlushBegin(this, info);
922 }
923 }
924 mutex_.Lock();
925 // no need to signal bg_cv_ as it will be signaled at the end of the
926 // flush process.
927}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnFlushCompleted()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnFlushCompleted ( ColumnFamilyData * cfd,
const MutableCFOptions & mutable_cf_options,
std::list< std::unique_ptr< FlushJobInfo > > * flush_jobs_info )
protected

db_impl_compaction_flush.cc 파일의 929 번째 라인에서 정의되었습니다.

931 {
932 assert(flush_jobs_info != nullptr);
933 if (immutable_db_options_.listeners.size() == 0U) {
934 return;
935 }
936 mutex_.AssertHeld();
937 if (shutting_down_.load(std::memory_order_acquire)) {
938 return;
939 }
940 bool triggered_writes_slowdown =
941 (cfd->current()->storage_info()->NumLevelFiles(0) >=
942 mutable_cf_options.level0_slowdown_writes_trigger);
943 bool triggered_writes_stop =
944 (cfd->current()->storage_info()->NumLevelFiles(0) >=
945 mutable_cf_options.level0_stop_writes_trigger);
946 // release lock while notifying events
947 mutex_.Unlock();
948 {
949 for (auto& info : *flush_jobs_info) {
950 info->triggered_writes_slowdown = triggered_writes_slowdown;
951 info->triggered_writes_stop = triggered_writes_stop;
952 for (const auto& listener : immutable_db_options_.listeners) {
953 listener->OnFlushCompleted(this, *info);
954 }
956 "DBImpl::NotifyOnFlushCompleted::PostAllOnFlushCompleted");
957 }
958 flush_jobs_info->clear();
959 }
960 mutex_.Lock();
961 // no need to signal bg_cv_ as it will be signaled at the end of the
962 // flush process.
963}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnManualFlushScheduled()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnManualFlushScheduled ( autovector< ColumnFamilyData * > cfds,
FlushReason flush_reason )
protected

db_impl_compaction_flush.cc 파일의 2259 번째 라인에서 정의되었습니다.

2260 {
2261 if (immutable_db_options_.listeners.size() == 0U) {
2262 return;
2263 }
2264 if (shutting_down_.load(std::memory_order_acquire)) {
2265 return;
2266 }
2267 std::vector<ManualFlushInfo> info;
2268 for (ColumnFamilyData* cfd : cfds) {
2269 info.push_back({cfd->GetID(), cfd->GetName(), flush_reason});
2270 }
2271 for (const auto& listener : immutable_db_options_.listeners) {
2272 listener->OnManualFlushScheduled(this, info);
2273 }
2274}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NotifyOnMemTableSealed()

void ROCKSDB_NAMESPACE::DBImpl::NotifyOnMemTableSealed ( ColumnFamilyData * cfd,
const MemTableInfo & mem_table_info )
protected

db_impl_write.cc 파일의 2369 번째 라인에서 정의되었습니다.

2370 {
2371 if (immutable_db_options_.listeners.size() == 0U) {
2372 return;
2373 }
2374 if (shutting_down_.load(std::memory_order_acquire)) {
2375 return;
2376 }
2377
2378 mutex_.Unlock();
2379 for (const auto& listener : immutable_db_options_.listeners) {
2380 listener->OnMemTableSealed(mem_table_info);
2381 }
2382 mutex_.Lock();
2383}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ num_running_compactions()

int ROCKSDB_NAMESPACE::DBImpl::num_running_compactions ( )
inline

db_impl.h 파일의 944 번째 라인에서 정의되었습니다.

944 {
945 mutex_.AssertHeld();
947 }

◆ num_running_flushes()

int ROCKSDB_NAMESPACE::DBImpl::num_running_flushes ( )
inline

db_impl.h 파일의 937 번째 라인에서 정의되었습니다.

937 {
938 mutex_.AssertHeld();
940 }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NumberLevels() [1/2]

virtual int ROCKSDB_NAMESPACE::DB::NumberLevels ( )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1613 번째 라인에서 정의되었습니다.

1613{ return NumberLevels(DefaultColumnFamily()); }

◆ NumberLevels() [2/2]

int ROCKSDB_NAMESPACE::DBImpl::NumberLevels ( ColumnFamilyHandle * column_family)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 1913 번째 라인에서 정의되었습니다.

1913 {
1914 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1915 return cfh->cfd()->NumberLevels();
1916}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Open()

Status ROCKSDB_NAMESPACE::DBImpl::Open ( const DBOptions & db_options,
const std::string & name,
const std::vector< ColumnFamilyDescriptor > & column_families,
std::vector< ColumnFamilyHandle * > * handles,
DB ** dbptr,
const bool seq_per_batch,
const bool batch_per_txn,
const bool is_retry,
bool * can_retry )
static

db_impl_open.cc 파일의 2015 번째 라인에서 정의되었습니다.

2019 {
2020 const WriteOptions write_options(Env::IOActivity::kDBOpen);
2021 const ReadOptions read_options(Env::IOActivity::kDBOpen);
2022
2023 Status s = ValidateOptionsByTable(db_options, column_families);
2024 if (!s.ok()) {
2025 return s;
2026 }
2027
2028 s = ValidateOptions(db_options, column_families);
2029 if (!s.ok()) {
2030 return s;
2031 }
2032
2033 *dbptr = nullptr;
2034 assert(handles);
2035 handles->clear();
2036
2037 size_t max_write_buffer_size = 0;
2038 for (const auto& cf : column_families) {
2039 max_write_buffer_size =
2040 std::max(max_write_buffer_size, cf.options.write_buffer_size);
2041 }
2042
2043 DBImpl* impl = new DBImpl(db_options, dbname, seq_per_batch, batch_per_txn);
2044 if (!impl->immutable_db_options_.info_log) {
2045 s = impl->init_logger_creation_s_;
2046 delete impl;
2047 return s;
2048 } else {
2049 assert(impl->init_logger_creation_s_.ok());
2050 }
2051 s = impl->env_->CreateDirIfMissing(impl->immutable_db_options_.GetWalDir());
2052 if (s.ok()) {
2053 std::vector<std::string> paths;
2054 for (auto& db_path : impl->immutable_db_options_.db_paths) {
2055 paths.emplace_back(db_path.path);
2056 }
2057 for (auto& cf : column_families) {
2058 for (auto& cf_path : cf.options.cf_paths) {
2059 paths.emplace_back(cf_path.path);
2060 }
2061 }
2062 for (const auto& path : paths) {
2063 s = impl->env_->CreateDirIfMissing(path);
2064 if (!s.ok()) {
2065 break;
2066 }
2067 }
2068
2069 // For recovery from NoSpace() error, we can only handle
2070 // the case where the database is stored in a single path
2071 if (paths.size() <= 1) {
2072 impl->error_handler_.EnableAutoRecovery();
2073 }
2074 }
2075 if (s.ok()) {
2076 s = impl->CreateArchivalDirectory();
2077 }
2078 if (!s.ok()) {
2079 delete impl;
2080 return s;
2081 }
2082
2083 impl->wal_in_db_path_ = impl->immutable_db_options_.IsWalDirSameAsDBPath();
2084 RecoveryContext recovery_ctx;
2085 impl->options_mutex_.Lock();
2086 impl->mutex_.Lock();
2087
2088 // Handles create_if_missing, error_if_exists
2089 uint64_t recovered_seq(kMaxSequenceNumber);
2090 s = impl->Recover(column_families, false /* read_only */,
2091 false /* error_if_wal_file_exists */,
2092 false /* error_if_data_exists_in_wals */, is_retry,
2093 &recovered_seq, &recovery_ctx, can_retry);
2094 if (s.ok()) {
2095 uint64_t new_log_number = impl->versions_->NewFileNumber();
2096 log::Writer* new_log = nullptr;
2097 const size_t preallocate_block_size =
2098 impl->GetWalPreallocateBlockSize(max_write_buffer_size);
2099 s = impl->CreateWAL(write_options, new_log_number, 0 /*recycle_log_number*/,
2100 preallocate_block_size, &new_log);
2101 if (s.ok()) {
2102 // Prevent log files created by previous instance from being recycled.
2103 // They might be in alive_log_file_, and might get recycled otherwise.
2104 impl->min_log_number_to_recycle_ = new_log_number;
2105 }
2106 if (s.ok()) {
2107 InstrumentedMutexLock wl(&impl->log_write_mutex_);
2108 impl->logfile_number_ = new_log_number;
2109 assert(new_log != nullptr);
2110 assert(impl->logs_.empty());
2111 impl->logs_.emplace_back(new_log_number, new_log);
2112 }
2113
2114 if (s.ok()) {
2115 impl->alive_log_files_.emplace_back(impl->logfile_number_);
2116 // In WritePrepared there could be gap in sequence numbers. This breaks
2117 // the trick we use in kPointInTimeRecovery which assumes the first seq in
2118 // the log right after the corrupted log is one larger than the last seq
2119 // we read from the wals. To let this trick keep working, we add a dummy
2120 // entry with the expected sequence to the first log right after recovery.
2121 // In non-WritePrepared case also the new log after recovery could be
2122 // empty, and thus missing the consecutive seq hint to distinguish
2123 // middle-log corruption to corrupted-log-remained-after-recovery. This
2124 // case also will be addressed by a dummy write.
2125 if (recovered_seq != kMaxSequenceNumber) {
2126 WriteBatch empty_batch;
2127 WriteBatchInternal::SetSequence(&empty_batch, recovered_seq);
2128 uint64_t log_used, log_size;
2129 log::Writer* log_writer = impl->logs_.back().writer;
2130 LogFileNumberSize& log_file_number_size = impl->alive_log_files_.back();
2131
2132 assert(log_writer->get_log_number() == log_file_number_size.number);
2133 impl->mutex_.AssertHeld();
2134 s = impl->WriteToWAL(empty_batch, write_options, log_writer, &log_used,
2135 &log_size, log_file_number_size);
2136 if (s.ok()) {
2137 // Need to fsync, otherwise it might get lost after a power reset.
2138 s = impl->FlushWAL(write_options, false);
2139 TEST_SYNC_POINT_CALLBACK("DBImpl::Open::BeforeSyncWAL", /*arg=*/&s);
2140 IOOptions opts;
2141 if (s.ok()) {
2142 s = WritableFileWriter::PrepareIOOptions(write_options, opts);
2143 }
2144 if (s.ok()) {
2145 s = log_writer->file()->Sync(opts,
2146 impl->immutable_db_options_.use_fsync);
2147 }
2148 }
2149 }
2150 }
2151 }
2152 if (s.ok()) {
2153 s = impl->LogAndApplyForRecovery(recovery_ctx);
2154 }
2155
2156 if (s.ok() && !impl->immutable_db_options_.write_identity_file) {
2157 // On successful recovery, delete an obsolete IDENTITY file to avoid DB ID
2158 // inconsistency
2159 impl->env_->DeleteFile(IdentityFileName(impl->dbname_))
2160 .PermitUncheckedError();
2161 }
2162
2163 if (s.ok() && impl->immutable_db_options_.persist_stats_to_disk) {
2164 impl->mutex_.AssertHeld();
2165 s = impl->InitPersistStatsColumnFamily();
2166 }
2167
2168 if (s.ok()) {
2169 // set column family handles
2170 for (const auto& cf : column_families) {
2171 auto cfd =
2172 impl->versions_->GetColumnFamilySet()->GetColumnFamily(cf.name);
2173 if (cfd != nullptr) {
2174 handles->push_back(
2175 new ColumnFamilyHandleImpl(cfd, impl, &impl->mutex_));
2176 impl->NewThreadStatusCfInfo(cfd);
2177 } else {
2178 if (db_options.create_missing_column_families) {
2179 // missing column family, create it
2180 ColumnFamilyHandle* handle = nullptr;
2181 impl->mutex_.Unlock();
2182 // NOTE: the work normally done in WrapUpCreateColumnFamilies will
2183 // be done separately below.
2184 s = impl->CreateColumnFamilyImpl(read_options, write_options,
2185 cf.options, cf.name, &handle);
2186 impl->mutex_.Lock();
2187 if (s.ok()) {
2188 handles->push_back(handle);
2189 } else {
2190 break;
2191 }
2192 } else {
2193 s = Status::InvalidArgument("Column family not found", cf.name);
2194 break;
2195 }
2196 }
2197 }
2198 }
2199
2200 if (s.ok()) {
2201 SuperVersionContext sv_context(/* create_superversion */ true);
2202 for (auto cfd : *impl->versions_->GetColumnFamilySet()) {
2203 impl->InstallSuperVersionAndScheduleWork(
2204 cfd, &sv_context, *cfd->GetLatestMutableCFOptions());
2205 }
2206 sv_context.Clean();
2207 }
2208
2209 if (s.ok() && impl->immutable_db_options_.persist_stats_to_disk) {
2210 // try to read format version
2211 s = impl->PersistentStatsProcessFormatVersion();
2212 }
2213
2214 if (s.ok()) {
2215 for (auto cfd : *impl->versions_->GetColumnFamilySet()) {
2216 if (!cfd->mem()->IsSnapshotSupported()) {
2217 impl->is_snapshot_supported_ = false;
2218 }
2219 if (cfd->ioptions()->merge_operator != nullptr &&
2220 !cfd->mem()->IsMergeOperatorSupported()) {
2221 s = Status::InvalidArgument(
2222 "The memtable of column family %s does not support merge operator "
2223 "its options.merge_operator is non-null",
2224 cfd->GetName().c_str());
2225 }
2226 if (!s.ok()) {
2227 break;
2228 }
2229 }
2230 }
2231 TEST_SYNC_POINT("DBImpl::Open:Opened");
2232 Status persist_options_status;
2233 if (s.ok()) {
2234 // Persist RocksDB Options before scheduling the compaction.
2235 // The WriteOptionsFile() will release and lock the mutex internally.
2236 persist_options_status =
2237 impl->WriteOptionsFile(write_options, true /*db_mutex_already_held*/);
2238 *dbptr = impl;
2239 impl->opened_successfully_ = true;
2240 } else {
2241 persist_options_status.PermitUncheckedError();
2242 }
2243 impl->mutex_.Unlock();
2244
2245 auto sfm = static_cast<SstFileManagerImpl*>(
2246 impl->immutable_db_options_.sst_file_manager.get());
2247 if (s.ok() && sfm) {
2248 // Set Statistics ptr for SstFileManager to dump the stats of
2249 // DeleteScheduler.
2250 sfm->SetStatisticsPtr(impl->immutable_db_options_.statistics);
2251 ROCKS_LOG_INFO(impl->immutable_db_options_.info_log,
2252 "SstFileManager instance %p", sfm);
2253
2254 impl->TrackExistingDataFiles(recovery_ctx.existing_data_files_);
2255
2256 // Reserve some disk buffer space. This is a heuristic - when we run out
2257 // of disk space, this ensures that there is at least write_buffer_size
2258 // amount of free space before we resume DB writes. In low disk space
2259 // conditions, we want to avoid a lot of small L0 files due to frequent
2260 // WAL write failures and resultant forced flushes
2261 sfm->ReserveDiskBuffer(max_write_buffer_size,
2262 impl->immutable_db_options_.db_paths[0].path);
2263 }
2264
2265 if (s.ok()) {
2266 // When the DB is stopped, it's possible that there are some .trash files
2267 // that were not deleted yet, when we open the DB we will find these .trash
2268 // files and schedule them to be deleted (or delete immediately if
2269 // SstFileManager was not used).
2270 // Note that we only start doing this and below delete obsolete file after
2271 // `TrackExistingDataFiles` are called, the `max_trash_db_ratio` is
2272 // ineffective otherwise and these files' deletion won't be rate limited
2273 // which can cause discard stall.
2274 for (const auto& path : impl->CollectAllDBPaths()) {
2275 DeleteScheduler::CleanupDirectory(impl->immutable_db_options_.env, sfm,
2276 path)
2277 .PermitUncheckedError();
2278 }
2279 impl->mutex_.Lock();
2280 // This will do a full scan.
2281 impl->DeleteObsoleteFiles();
2282 TEST_SYNC_POINT("DBImpl::Open:AfterDeleteFiles");
2283 impl->MaybeScheduleFlushOrCompaction();
2284 impl->mutex_.Unlock();
2285 }
2286
2287 if (s.ok()) {
2288 ROCKS_LOG_HEADER(impl->immutable_db_options_.info_log, "DB pointer %p",
2289 impl);
2290 LogFlush(impl->immutable_db_options_.info_log);
2291 if (!impl->WALBufferIsEmpty()) {
2292 s = impl->FlushWAL(write_options, false);
2293 if (s.ok()) {
2294 // Sync is needed otherwise WAL buffered data might get lost after a
2295 // power reset.
2296 log::Writer* log_writer = impl->logs_.back().writer;
2297 IOOptions opts;
2298 s = WritableFileWriter::PrepareIOOptions(write_options, opts);
2299 if (s.ok()) {
2300 s = log_writer->file()->Sync(opts,
2301 impl->immutable_db_options_.use_fsync);
2302 }
2303 }
2304 }
2305 if (s.ok() && !persist_options_status.ok()) {
2306 s = Status::IOError(
2307 "DB::Open() failed --- Unable to persist Options file",
2308 persist_options_status.ToString());
2309 }
2310 }
2311 if (!s.ok()) {
2312 ROCKS_LOG_WARN(impl->immutable_db_options_.info_log,
2313 "DB::Open() failed: %s", s.ToString().c_str());
2314 }
2315 if (s.ok()) {
2316 s = impl->StartPeriodicTaskScheduler();
2317 }
2318 if (s.ok()) {
2319 s = impl->RegisterRecordSeqnoTimeWorker(read_options, write_options,
2320 recovery_ctx.is_new_db_);
2321 }
2322 impl->options_mutex_.Unlock();
2323 if (!s.ok()) {
2324 for (auto* h : *handles) {
2325 delete h;
2326 }
2327 handles->clear();
2328 delete impl;
2329 *dbptr = nullptr;
2330 }
2331 return s;
2332}
static Status ValidateOptions(const DBOptions &db_options)
#define ROCKS_LOG_HEADER(LGR, FMT,...)
Definition logging.h:28
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ operator=()

void ROCKSDB_NAMESPACE::DBImpl::operator= ( const DBImpl & )
delete
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ OwnTablesAndLogs()

virtual bool ROCKSDB_NAMESPACE::DBImpl::OwnTablesAndLogs ( ) const
inlineprotectedvirtual

ROCKSDB_NAMESPACE::DBImplFollower, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.h 파일의 1621 번째 라인에서 정의되었습니다.

1621{ return true; }

◆ PauseBackgroundWork()

Status ROCKSDB_NAMESPACE::DBImpl::PauseBackgroundWork ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 1659 번째 라인에서 정의되었습니다.

1659 {
1660 InstrumentedMutexLock guard_lock(&mutex_);
1662 while (bg_bottom_compaction_scheduled_ > 0 || bg_compaction_scheduled_ > 0 ||
1663 bg_flush_scheduled_ > 0) {
1664 bg_cv_.Wait();
1665 }
1667 return Status::OK();
1668}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PersistentStatsColumnFamily()

ColumnFamilyHandle * ROCKSDB_NAMESPACE::DBImpl::PersistentStatsColumnFamily ( ) const

db_impl.cc 파일의 2156 번째 라인에서 정의되었습니다.

2156 {
2158}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PersistentStatsProcessFormatVersion()

Status ROCKSDB_NAMESPACE::DBImpl::PersistentStatsProcessFormatVersion ( )
private

db_impl_open.cc 파일의 868 번째 라인에서 정의되었습니다.

868 {
869 mutex_.AssertHeld();
870 Status s;
871 // persist version when stats CF doesn't exist
872 bool should_persist_format_version = !persistent_stats_cfd_exists_;
873 mutex_.Unlock();
874 if (persistent_stats_cfd_exists_) {
875 // Check persistent stats format version compatibility. Drop and recreate
876 // persistent stats CF if format version is incompatible
877 uint64_t format_version_recovered = 0;
878 Status s_format = DecodePersistentStatsVersionNumber(
879 this, StatsVersionKeyType::kFormatVersion, &format_version_recovered);
880 uint64_t compatible_version_recovered = 0;
881 Status s_compatible = DecodePersistentStatsVersionNumber(
882 this, StatsVersionKeyType::kCompatibleVersion,
883 &compatible_version_recovered);
884 // abort reading from existing stats CF if any of following is true:
885 // 1. failed to read format version or compatible version from disk
886 // 2. sst's format version is greater than current format version, meaning
887 // this sst is encoded with a newer RocksDB release, and current compatible
888 // version is below the sst's compatible version
889 if (!s_format.ok() || !s_compatible.ok() ||
890 (kStatsCFCurrentFormatVersion < format_version_recovered &&
891 kStatsCFCompatibleFormatVersion < compatible_version_recovered)) {
892 if (!s_format.ok() || !s_compatible.ok()) {
895 "Recreating persistent stats column family since reading "
896 "persistent stats version key failed. Format key: %s, compatible "
897 "key: %s",
898 s_format.ToString().c_str(), s_compatible.ToString().c_str());
899 } else {
902 "Recreating persistent stats column family due to corrupted or "
903 "incompatible format version. Recovered format: %" PRIu64
904 "; recovered format compatible since: %" PRIu64 "\n",
905 format_version_recovered, compatible_version_recovered);
906 }
907 s = DropColumnFamily(persist_stats_cf_handle_);
908 if (s.ok()) {
909 s = DestroyColumnFamilyHandle(persist_stats_cf_handle_);
910 }
911 ColumnFamilyHandle* handle = nullptr;
912 if (s.ok()) {
913 ColumnFamilyOptions cfo;
915 s = CreateColumnFamilyImpl(ReadOptions(Env::IOActivity::kDBOpen),
916 WriteOptions(Env::IOActivity::kDBOpen), cfo,
917 kPersistentStatsColumnFamilyName, &handle);
918 }
919 if (s.ok()) {
920 persist_stats_cf_handle_ = static_cast<ColumnFamilyHandleImpl*>(handle);
921 // should also persist version here because old stats CF is discarded
922 should_persist_format_version = true;
923 }
924 }
925 }
926 if (should_persist_format_version) {
927 // Persistent stats CF being created for the first time, need to write
928 // format version key
929 WriteBatch batch;
930 if (s.ok()) {
931 s = batch.Put(persist_stats_cf_handle_, kFormatVersionKeyString,
932 std::to_string(kStatsCFCurrentFormatVersion));
933 }
934 if (s.ok()) {
935 s = batch.Put(persist_stats_cf_handle_, kCompatibleVersionKeyString,
936 std::to_string(kStatsCFCompatibleFormatVersion));
937 }
938 if (s.ok()) {
939 // TODO: plumb Env::IOActivity, Env::IOPriority
940 WriteOptions wo;
941 wo.low_pri = true;
942 wo.no_slowdown = true;
943 wo.sync = false;
944 s = Write(wo, &batch);
945 }
946 }
947 mutex_.Lock();
948 return s;
949}
Status Write(const WriteOptions &options, WriteBatch *updates) override
Status DecodePersistentStatsVersionNumber(DBImpl *db, StatsVersionKeyType type, uint64_t *version_number)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PersistStats()

void ROCKSDB_NAMESPACE::DBImpl::PersistStats ( )

db_impl.cc 파일의 1004 번째 라인에서 정의되었습니다.

1004 {
1005 TEST_SYNC_POINT("DBImpl::PersistStats:Entry");
1006 if (shutdown_initiated_) {
1007 return;
1008 }
1009 TEST_SYNC_POINT("DBImpl::PersistStats:StartRunning");
1010 uint64_t now_seconds =
1012
1013 Statistics* statistics = immutable_db_options_.stats;
1014 if (!statistics) {
1015 return;
1016 }
1017 size_t stats_history_size_limit = 0;
1018 {
1019 InstrumentedMutexLock l(&mutex_);
1020 stats_history_size_limit = mutable_db_options_.stats_history_buffer_size;
1021 }
1022
1023 std::map<std::string, uint64_t> stats_map;
1024 if (!statistics->getTickerMap(&stats_map)) {
1025 return;
1026 }
1028 "------- PERSISTING STATS -------");
1029
1031 WriteBatch batch;
1032 Status s = Status::OK();
1033 if (stats_slice_initialized_) {
1035 "Reading %" ROCKSDB_PRIszt " stats from statistics\n",
1036 stats_slice_.size());
1037 for (const auto& stat : stats_map) {
1038 if (s.ok()) {
1039 char key[100];
1040 int length =
1041 EncodePersistentStatsKey(now_seconds, stat.first, 100, key);
1042 // calculate the delta from last time
1043 if (stats_slice_.find(stat.first) != stats_slice_.end()) {
1044 uint64_t delta = stat.second - stats_slice_[stat.first];
1045 s = batch.Put(persist_stats_cf_handle_,
1046 Slice(key, std::min(100, length)),
1047 std::to_string(delta));
1048 }
1049 }
1050 }
1051 }
1053 std::swap(stats_slice_, stats_map);
1054 if (s.ok()) {
1055 // TODO: plumb Env::IOActivity, Env::IOPriority
1056 WriteOptions wo;
1057 wo.low_pri = true;
1058 wo.no_slowdown = true;
1059 wo.sync = false;
1060 s = Write(wo, &batch);
1061 }
1062 if (!s.ok()) {
1064 "Writing to persistent stats CF failed -- %s",
1065 s.ToString().c_str());
1066 } else {
1068 "Writing %" ROCKSDB_PRIszt " stats with timestamp %" PRIu64
1069 " to persistent stats CF succeeded",
1070 stats_slice_.size(), now_seconds);
1071 }
1072 // TODO(Zhongyi): add purging for persisted data
1073 } else {
1074 InstrumentedMutexLock l(&stats_history_mutex_);
1075 // calculate the delta from last time
1076 if (stats_slice_initialized_) {
1077 std::map<std::string, uint64_t> stats_delta;
1078 for (const auto& stat : stats_map) {
1079 if (stats_slice_.find(stat.first) != stats_slice_.end()) {
1080 stats_delta[stat.first] = stat.second - stats_slice_[stat.first];
1081 }
1082 }
1084 "Storing %" ROCKSDB_PRIszt " stats with timestamp %" PRIu64
1085 " to in-memory stats history",
1086 stats_slice_.size(), now_seconds);
1087 stats_history_[now_seconds] = std::move(stats_delta);
1088 }
1090 std::swap(stats_slice_, stats_map);
1091 TEST_SYNC_POINT("DBImpl::PersistStats:StatsCopied");
1092
1093 // delete older stats snapshots to control memory consumption
1094 size_t stats_history_size = EstimateInMemoryStatsHistorySize();
1095 bool purge_needed = stats_history_size > stats_history_size_limit;
1097 "[Pre-GC] In-memory stats history size: %" ROCKSDB_PRIszt
1098 " bytes, slice count: %" ROCKSDB_PRIszt,
1099 stats_history_size, stats_history_.size());
1100 while (purge_needed && !stats_history_.empty()) {
1101 stats_history_.erase(stats_history_.begin());
1102 purge_needed =
1103 EstimateInMemoryStatsHistorySize() > stats_history_size_limit;
1104 }
1106 "[Post-GC] In-memory stats history size: %" ROCKSDB_PRIszt
1107 " bytes, slice count: %" ROCKSDB_PRIszt,
1108 stats_history_size, stats_history_.size());
1109 }
1110 TEST_SYNC_POINT("DBImpl::PersistStats:End");
1111}
size_t EstimateInMemoryStatsHistorySize() const
Definition db_impl.cc:986
std::map< std::string, uint64_t > stats_slice_
Definition db_impl.h:2774
int EncodePersistentStatsKey(uint64_t now_seconds, const std::string &key, int size, char *buf)
void swap(ROCKSDB_NAMESPACE::port::WindowsThread &th1, ROCKSDB_NAMESPACE::port::WindowsThread &th2)
Definition win_thread.h:111
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PickCompactionFromQueue()

ColumnFamilyData * ROCKSDB_NAMESPACE::DBImpl::PickCompactionFromQueue ( std::unique_ptr< TaskLimiterToken > * token,
LogBuffer * log_buffer )
private

db_impl_compaction_flush.cc 파일의 2999 번째 라인에서 정의되었습니다.

3000 {
3001 assert(!compaction_queue_.empty());
3002 assert(*token == nullptr);
3003 autovector<ColumnFamilyData*> throttled_candidates;
3004 ColumnFamilyData* cfd = nullptr;
3005 while (!compaction_queue_.empty()) {
3006 auto first_cfd = *compaction_queue_.begin();
3007 compaction_queue_.pop_front();
3008 assert(first_cfd->queued_for_compaction());
3009 if (!RequestCompactionToken(first_cfd, false, token, log_buffer)) {
3010 throttled_candidates.push_back(first_cfd);
3011 continue;
3012 }
3013 cfd = first_cfd;
3014 cfd->set_queued_for_compaction(false);
3015 break;
3016 }
3017 // Add throttled compaction candidates back to queue in the original order.
3018 for (auto iter = throttled_candidates.rbegin();
3019 iter != throttled_candidates.rend(); ++iter) {
3020 compaction_queue_.push_front(*iter);
3021 }
3022 return cfd;
3023}
bool RequestCompactionToken(ColumnFamilyData *cfd, bool force, std::unique_ptr< TaskLimiterToken > *token, LogBuffer *log_buffer)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PipelinedWriteImpl()

Status ROCKSDB_NAMESPACE::DBImpl::PipelinedWriteImpl ( const WriteOptions & options,
WriteBatch * updates,
WriteCallback * callback = nullptr,
UserWriteCallback * user_write_cb = nullptr,
uint64_t * log_used = nullptr,
uint64_t log_ref = 0,
bool disable_memtable = false,
uint64_t * seq_used = nullptr )
protected

db_impl_write.cc 파일의 882 번째 라인에서 정의되었습니다.

886 {
887 PERF_TIMER_GUARD(write_pre_and_post_process_time);
888 StopWatch write_sw(immutable_db_options_.clock, stats_, DB_WRITE);
889
890 WriteContext write_context;
891
892 WriteThread::Writer w(write_options, my_batch, callback, user_write_cb,
893 log_ref, disable_memtable, /*_batch_cnt=*/0,
894 /*_pre_release_callback=*/nullptr);
896 TEST_SYNC_POINT("DBImplWrite::PipelinedWriteImpl:AfterJoinBatchGroup");
897 if (w.state == WriteThread::STATE_GROUP_LEADER) {
898 WriteThread::WriteGroup wal_write_group;
899 if (w.callback && !w.callback->AllowWriteBatching()) {
901 }
902 LogContext log_context(!write_options.disableWAL && write_options.sync);
903 // PreprocessWrite does its own perf timing.
904 PERF_TIMER_STOP(write_pre_and_post_process_time);
905 w.status = PreprocessWrite(write_options, &log_context, &write_context);
906 PERF_TIMER_START(write_pre_and_post_process_time);
907
908 // This can set non-OK status if callback fail.
910 write_thread_.EnterAsBatchGroupLeader(&w, &wal_write_group);
911 const SequenceNumber current_sequence =
912 write_thread_.UpdateLastSequence(versions_->LastSequence()) + 1;
913 size_t total_count = 0;
914 size_t total_byte_size = 0;
915
916 if (w.status.ok()) {
917 SequenceNumber next_sequence = current_sequence;
918 for (auto* writer : wal_write_group) {
919 assert(writer);
920 if (writer->CheckCallback(this)) {
921 if (writer->ShouldWriteToMemtable()) {
922 writer->sequence = next_sequence;
923 size_t count = WriteBatchInternal::Count(writer->batch);
924 total_byte_size = WriteBatchInternal::AppendedByteSize(
925 total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
926 next_sequence += count;
927 total_count += count;
928 }
929 }
930 }
931 // TODO: this use of operator bool on `tracer_` can avoid unnecessary lock
932 // grabs but does not seem thread-safe.
933 if (tracer_) {
934 InstrumentedMutexLock lock(&trace_mutex_);
935 if (tracer_ != nullptr && tracer_->IsWriteOrderPreserved()) {
936 for (auto* writer : wal_write_group) {
937 if (writer->CallbackFailed()) {
938 // When optimisitc txn conflict checking fails, we should
939 // not record to trace.
940 continue;
941 }
942 // TODO: maybe handle the tracing status?
943 tracer_->Write(writer->batch).PermitUncheckedError();
944 }
945 }
946 }
947 if (w.disable_wal) {
948 has_unpersisted_data_.store(true, std::memory_order_relaxed);
949 }
950 write_thread_.UpdateLastSequence(current_sequence + total_count - 1);
951 }
952
953 auto stats = default_cf_internal_stats_;
954 stats->AddDBStats(InternalStats::kIntStatsNumKeysWritten, total_count);
955 RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
956 stats->AddDBStats(InternalStats::kIntStatsBytesWritten, total_byte_size);
957 RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
958 RecordInHistogram(stats_, BYTES_PER_WRITE, total_byte_size);
959
960 PERF_TIMER_STOP(write_pre_and_post_process_time);
961
962 IOStatus io_s;
963 io_s.PermitUncheckedError(); // Allow io_s to be uninitialized
964
965 if (w.status.ok() && !write_options.disableWAL) {
966 PERF_TIMER_GUARD(write_wal_time);
967 stats->AddDBStats(InternalStats::kIntStatsWriteDoneBySelf, 1);
968 RecordTick(stats_, WRITE_DONE_BY_SELF, 1);
969 if (wal_write_group.size > 1) {
970 stats->AddDBStats(InternalStats::kIntStatsWriteDoneByOther,
971 wal_write_group.size - 1);
972 RecordTick(stats_, WRITE_DONE_BY_OTHER, wal_write_group.size - 1);
973 }
974 assert(log_context.log_file_number_size);
975 LogFileNumberSize& log_file_number_size =
976 *(log_context.log_file_number_size);
977 io_s =
978 WriteToWAL(wal_write_group, log_context.writer, log_used,
979 log_context.need_log_sync, log_context.need_log_dir_sync,
980 current_sequence, log_file_number_size);
981 w.status = io_s;
982 }
983
984 if (!io_s.ok()) {
985 // Check WriteToWAL status
986 WALIOStatusCheck(io_s);
987 } else if (!w.CallbackFailed()) {
988 WriteStatusCheck(w.status);
989 }
990
991 VersionEdit synced_wals;
992 if (log_context.need_log_sync) {
993 InstrumentedMutexLock l(&log_write_mutex_);
994 if (w.status.ok()) {
995 MarkLogsSynced(logfile_number_, log_context.need_log_dir_sync,
996 &synced_wals);
997 } else {
998 MarkLogsNotSynced(logfile_number_);
999 }
1000 }
1001 if (w.status.ok() && synced_wals.IsWalAddition()) {
1002 InstrumentedMutexLock l(&mutex_);
1003 // TODO: plumb Env::IOActivity, Env::IOPriority
1004 const ReadOptions read_options;
1005 w.status = ApplyWALToManifest(read_options, write_options, &synced_wals);
1006 }
1007 write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
1008 }
1009
1010 // NOTE: the memtable_write_group is declared before the following
1011 // `if` statement because its lifetime needs to be longer
1012 // that the inner context of the `if` as a reference to it
1013 // may be used further below within the outer _write_thread
1014 WriteThread::WriteGroup memtable_write_group;
1015
1016 if (w.state == WriteThread::STATE_MEMTABLE_WRITER_LEADER) {
1017 PERF_TIMER_FOR_WAIT_GUARD(write_memtable_time);
1018 assert(w.ShouldWriteToMemtable());
1019 write_thread_.EnterAsMemTableWriter(&w, &memtable_write_group);
1020 if (memtable_write_group.size > 1 &&
1022 write_thread_.LaunchParallelMemTableWriters(&memtable_write_group);
1023 } else {
1024 memtable_write_group.status = WriteBatchInternal::InsertInto(
1025 memtable_write_group, w.sequence, column_family_memtables_.get(),
1026 &flush_scheduler_, &trim_history_scheduler_,
1027 write_options.ignore_missing_column_families, 0 /*log_number*/, this,
1028 false /*concurrent_memtable_writes*/, seq_per_batch_, batch_per_txn_);
1029 versions_->SetLastSequence(memtable_write_group.last_sequence);
1030 write_thread_.ExitAsMemTableWriter(&w, memtable_write_group);
1031 }
1032 } else {
1033 // NOTE: the memtable_write_group is never really used,
1034 // so we need to set its status to pass ASSERT_STATUS_CHECKED
1035 memtable_write_group.status.PermitUncheckedError();
1036 }
1037 if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_CALLER) {
1039 }
1040 if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
1041 PERF_TIMER_STOP(write_pre_and_post_process_time);
1042 PERF_TIMER_FOR_WAIT_GUARD(write_memtable_time);
1043
1044 assert(w.ShouldWriteToMemtable());
1045 ColumnFamilyMemTablesImpl column_family_memtables(
1046 versions_->GetColumnFamilySet());
1047 w.status = WriteBatchInternal::InsertInto(
1048 &w, w.sequence, &column_family_memtables, &flush_scheduler_,
1049 &trim_history_scheduler_, write_options.ignore_missing_column_families,
1050 0 /*log_number*/, this, true /*concurrent_memtable_writes*/,
1051 false /*seq_per_batch*/, 0 /*batch_cnt*/, true /*batch_per_txn*/,
1052 write_options.memtable_insert_hint_per_batch);
1053
1054 PERF_TIMER_STOP(write_memtable_time);
1055 PERF_TIMER_START(write_pre_and_post_process_time);
1056
1058 MemTableInsertStatusCheck(w.status);
1059 versions_->SetLastSequence(w.write_group->last_sequence);
1060 write_thread_.ExitAsMemTableWriter(&w, *w.write_group);
1061 }
1062 }
1063 if (seq_used != nullptr) {
1064 *seq_used = w.sequence;
1065 }
1066
1067 assert(w.state == WriteThread::STATE_COMPLETED);
1068 return w.FinalStatus();
1069}
Status PreprocessWrite(const WriteOptions &write_options, LogContext *log_context, WriteContext *write_context)
void MarkLogsNotSynced(uint64_t up_to)
Definition db_impl.cc:1891
void WriteStatusCheck(const Status &status)
void MemTableInsertStatusCheck(const Status &memtable_insert_status)
void MarkLogsSynced(uint64_t up_to, bool synced_dir, VersionEdit *edit)
Definition db_impl.cc:1849
size_t EnterAsBatchGroupLeader(Writer *leader, WriteGroup *write_group)
bool CompleteParallelMemTableWriter(Writer *w)
void SetMemWritersEachStride(Writer *w)
void EnterAsMemTableWriter(Writer *leader, WriteGroup *write_grup)
SequenceNumber UpdateLastSequence(SequenceNumber sequence)
void LaunchParallelMemTableWriters(WriteGroup *write_group)
void ExitAsMemTableWriter(Writer *self, WriteGroup &write_group)
void ExitAsBatchGroupLeader(WriteGroup &write_group, Status &status)
#define PERF_TIMER_START(metric)
#define PERF_TIMER_FOR_WAIT_GUARD(metric)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PopFirstFromCompactionQueue()

ColumnFamilyData * ROCKSDB_NAMESPACE::DBImpl::PopFirstFromCompactionQueue ( )
private

db_impl_compaction_flush.cc 파일의 2972 번째 라인에서 정의되었습니다.

2972 {
2973 assert(!compaction_queue_.empty());
2974 auto cfd = *compaction_queue_.begin();
2975 compaction_queue_.pop_front();
2976 assert(cfd->queued_for_compaction());
2977 cfd->set_queued_for_compaction(false);
2978 return cfd;
2979}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PopFirstFromFlushQueue()

DBImpl::FlushRequest ROCKSDB_NAMESPACE::DBImpl::PopFirstFromFlushQueue ( )
private

db_impl_compaction_flush.cc 파일의 2981 번째 라인에서 정의되었습니다.

2981 {
2982 assert(!flush_queue_.empty());
2983 FlushRequest flush_req = std::move(flush_queue_.front());
2984 flush_queue_.pop_front();
2986 assert(flush_req.cfd_to_max_mem_id_to_persist.size() == 1);
2987 }
2988 for (const auto& elem : flush_req.cfd_to_max_mem_id_to_persist) {
2990 ColumnFamilyData* cfd = elem.first;
2991 assert(cfd);
2992 assert(cfd->queued_for_flush());
2993 cfd->set_queued_for_flush(false);
2994 }
2995 }
2996 return flush_req;
2997}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PrepareMultiGetKeys()

void ROCKSDB_NAMESPACE::DBImpl::PrepareMultiGetKeys ( const size_t num_keys,
bool sorted,
autovector< KeyContext *, MultiGetContext::MAX_BATCH_SIZE > * key_ptrs )
private

db_impl.cc 파일의 3011 번째 라인에서 정의되었습니다.

3013 {
3014 if (sorted_input) {
3015#ifndef NDEBUG
3016 assert(std::is_sorted(sorted_keys->begin(), sorted_keys->end(),
3017 CompareKeyContext()));
3018#endif
3019 return;
3020 }
3021
3022 std::sort(sorted_keys->begin(), sorted_keys->begin() + num_keys,
3023 CompareKeyContext());
3024}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PreprocessWrite()

Status ROCKSDB_NAMESPACE::DBImpl::PreprocessWrite ( const WriteOptions & write_options,
LogContext * log_context,
WriteContext * write_context )
private

db_impl_write.cc 파일의 1397 번째 라인에서 정의되었습니다.

1399 {
1400 assert(write_context != nullptr && log_context != nullptr);
1401 Status status;
1402
1404 InstrumentedMutexLock l(&mutex_);
1405 status = error_handler_.GetBGError();
1406 }
1407
1408 PERF_TIMER_GUARD(write_scheduling_flushes_compactions_time);
1409
1410 if (UNLIKELY(status.ok() && total_log_size_ > GetMaxTotalWalSize())) {
1411 assert(versions_);
1412 InstrumentedMutexLock l(&mutex_);
1413 const ColumnFamilySet* const column_families =
1414 versions_->GetColumnFamilySet();
1415 assert(column_families);
1416 size_t num_cfs = column_families->NumberOfColumnFamilies();
1417 assert(num_cfs >= 1);
1418 if (num_cfs > 1) {
1420 status = SwitchWAL(write_context);
1421 }
1422 }
1423
1424 if (UNLIKELY(status.ok() && write_buffer_manager_->ShouldFlush())) {
1425 // Before a new memtable is added in SwitchMemtable(),
1426 // write_buffer_manager_->ShouldFlush() will keep returning true. If another
1427 // thread is writing to another DB with the same write buffer, they may also
1428 // be flushed. We may end up with flushing much more DBs than needed. It's
1429 // suboptimal but still correct.
1430 InstrumentedMutexLock l(&mutex_);
1432 status = HandleWriteBufferManagerFlush(write_context);
1433 }
1434
1435 if (UNLIKELY(status.ok() && !trim_history_scheduler_.Empty())) {
1436 InstrumentedMutexLock l(&mutex_);
1437 status = TrimMemtableHistory(write_context);
1438 }
1439
1440 if (UNLIKELY(status.ok() && !flush_scheduler_.Empty())) {
1441 InstrumentedMutexLock l(&mutex_);
1443 status = ScheduleFlushes(write_context);
1444 }
1445
1446 PERF_TIMER_STOP(write_scheduling_flushes_compactions_time);
1447 PERF_TIMER_GUARD(write_pre_and_post_process_time);
1448
1449 if (UNLIKELY(status.ok() && (write_controller_.IsStopped() ||
1451 PERF_TIMER_STOP(write_pre_and_post_process_time);
1452 PERF_TIMER_FOR_WAIT_GUARD(write_delay_time);
1453 // We don't know size of curent batch so that we always use the size
1454 // for previous one. It might create a fairness issue that expiration
1455 // might happen for smaller writes but larger writes can go through.
1456 // Can optimize it if it is an issue.
1457 InstrumentedMutexLock l(&mutex_);
1458 status = DelayWrite(last_batch_group_size_, write_thread_, write_options);
1459 PERF_TIMER_START(write_pre_and_post_process_time);
1460 }
1461
1462 // If memory usage exceeded beyond a certain threshold,
1463 // write_buffer_manager_->ShouldStall() returns true to all threads writing to
1464 // all DBs and writers will be stalled.
1465 // It does soft checking because WriteBufferManager::buffer_limit_ has already
1466 // exceeded at this point so no new write (including current one) will go
1467 // through until memory usage is decreased.
1468 if (UNLIKELY(status.ok() && write_buffer_manager_->ShouldStall())) {
1470 InternalStats::kIntStatsWriteBufferManagerLimitStopsCounts, 1,
1471 true /* concurrent */);
1472 if (write_options.no_slowdown) {
1473 status = Status::Incomplete("Write stall");
1474 } else {
1475 InstrumentedMutexLock l(&mutex_);
1477 }
1478 }
1479 InstrumentedMutexLock l(&log_write_mutex_);
1480 if (status.ok() && log_context->need_log_sync) {
1481 // Wait until the parallel syncs are finished. Any sync process has to sync
1482 // the front log too so it is enough to check the status of front()
1483 // We do a while loop since log_sync_cv_ is signalled when any sync is
1484 // finished
1485 // Note: there does not seem to be a reason to wait for parallel sync at
1486 // this early step but it is not important since parallel sync (SyncWAL) and
1487 // need_log_sync are usually not used together.
1488 while (logs_.front().IsSyncing()) {
1490 }
1491 for (auto& log : logs_) {
1492 // This is just to prevent the logs to be synced by a parallel SyncWAL
1493 // call. We will do the actual syncing later after we will write to the
1494 // WAL.
1495 // Note: there does not seem to be a reason to set this early before we
1496 // actually write to the WAL
1497 log.PrepareForSync();
1498 }
1499 } else {
1500 log_context->need_log_sync = false;
1501 }
1502 log_context->writer = logs_.back().writer;
1503 log_context->need_log_dir_sync =
1504 log_context->need_log_dir_sync && !log_dir_synced_;
1505 log_context->log_file_number_size = std::addressof(alive_log_files_.back());
1506
1507 return status;
1508}
Status ScheduleFlushes(WriteContext *context)
Status DelayWrite(uint64_t num_bytes, WriteThread &write_thread, const WriteOptions &write_options)
Status HandleWriteBufferManagerFlush(WriteContext *write_context)
Status SwitchWAL(WriteContext *write_context)
uint64_t GetMaxTotalWalSize() const
Status TrimMemtableHistory(WriteContext *context)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PrintStatistics()

void ROCKSDB_NAMESPACE::DBImpl::PrintStatistics ( )
private

db_impl.cc 파일의 791 번째 라인에서 정의되었습니다.

791 {
792 auto dbstats = immutable_db_options_.stats;
793 if (dbstats) {
795 dbstats->ToString().c_str());
796 }
797}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PromoteL0()

Status ROCKSDB_NAMESPACE::DBImpl::PromoteL0 ( ColumnFamilyHandle * column_family,
int target_level )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl_experimental.cc 파일의 56 번째 라인에서 정의되었습니다.

56 {
57 assert(column_family);
58
59 if (target_level < 1) {
61 "PromoteL0 FAILED. Invalid target level %d\n", target_level);
62 return Status::InvalidArgument("Invalid target level");
63 }
64 // TODO: plumb Env::IOActivity, Env::IOPriority
65 const ReadOptions read_options;
66 const WriteOptions write_options;
67
68 Status status;
69 VersionEdit edit;
70 JobContext job_context(next_job_id_.fetch_add(1), true);
71 {
72 InstrumentedMutexLock l(&mutex_);
73 auto* cfd = static_cast<ColumnFamilyHandleImpl*>(column_family)->cfd();
74 const auto* vstorage = cfd->current()->storage_info();
75
76 if (target_level >= vstorage->num_levels()) {
78 "PromoteL0 FAILED. Target level %d does not exist\n",
79 target_level);
80 job_context.Clean();
81 status = Status::InvalidArgument("Target level does not exist");
82 return status;
83 }
84
85 // Sort L0 files by range.
86 const InternalKeyComparator* icmp = &cfd->internal_comparator();
87 auto l0_files = vstorage->LevelFiles(0);
88 std::sort(l0_files.begin(), l0_files.end(),
89 [icmp](FileMetaData* f1, FileMetaData* f2) {
90 return icmp->Compare(f1->largest, f2->largest) < 0;
91 });
92
93 // Check that no L0 file is being compacted and that they have
94 // non-overlapping ranges.
95 for (size_t i = 0; i < l0_files.size(); ++i) {
96 auto f = l0_files[i];
97 if (f->being_compacted) {
99 "PromoteL0 FAILED. File %" PRIu64 " being compacted\n",
100 f->fd.GetNumber());
101 job_context.Clean();
102 status =
103 Status::InvalidArgument("PromoteL0 called during L0 compaction");
104 return status;
105 }
106
107 if (i == 0) {
108 continue;
109 }
110 auto prev_f = l0_files[i - 1];
111 if (icmp->Compare(prev_f->largest, f->smallest) >= 0) {
113 "PromoteL0 FAILED. Files %" PRIu64 " and %" PRIu64
114 " have overlapping ranges\n",
115 prev_f->fd.GetNumber(), f->fd.GetNumber());
116 job_context.Clean();
117 status = Status::InvalidArgument("L0 has overlapping files");
118 return status;
119 }
120 }
121
122 // Check that all levels up to target_level are empty.
123 for (int level = 1; level <= target_level; ++level) {
124 if (vstorage->NumLevelFiles(level) > 0) {
126 "PromoteL0 FAILED. Level %d not empty\n", level);
127 job_context.Clean();
128 status = Status::InvalidArgument(
129 "All levels up to target_level "
130 "must be empty");
131 return status;
132 }
133 }
134
135 edit.SetColumnFamily(cfd->GetID());
136 for (const auto& f : l0_files) {
137 edit.DeleteFile(0, f->fd.GetNumber());
138 edit.AddFile(target_level, f->fd.GetNumber(), f->fd.GetPathId(),
139 f->fd.GetFileSize(), f->smallest, f->largest,
140 f->fd.smallest_seqno, f->fd.largest_seqno,
141 f->marked_for_compaction, f->temperature,
142 f->oldest_blob_file_number, f->oldest_ancester_time,
143 f->file_creation_time, f->epoch_number, f->file_checksum,
144 f->file_checksum_func_name, f->unique_id,
145 f->compensated_range_deletion_size, f->tail_size,
146 f->user_defined_timestamps_persisted);
147 }
148
149 status = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
150 read_options, write_options, &edit, &mutex_,
152 if (status.ok()) {
154 cfd, job_context.superversion_contexts.data(),
155 *cfd->GetLatestMutableCFOptions());
156 }
157 } // lock released here
159 job_context.Clean();
160
161 return status;
162}
#define f1
Definition ppc-asm.h:72
#define f2
Definition ppc-asm.h:73
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PurgeObsoleteFiles()

void ROCKSDB_NAMESPACE::DBImpl::PurgeObsoleteFiles ( JobContext & background_contet,
bool schedule_only = false )

db_impl_files.cc 파일의 417 번째 라인에서 정의되었습니다.

417 {
418 TEST_SYNC_POINT("DBImpl::PurgeObsoleteFiles:Begin");
419 // we'd better have sth to delete
420 assert(state.HaveSomethingToDelete());
421
422 // FindObsoleteFiles() should've populated this so nonzero
423 assert(state.manifest_file_number != 0);
424
425 // Now, convert lists to unordered sets, WITHOUT mutex held; set is slow.
426 std::unordered_set<uint64_t> sst_live_set(state.sst_live.begin(),
427 state.sst_live.end());
428 std::unordered_set<uint64_t> blob_live_set(state.blob_live.begin(),
429 state.blob_live.end());
430 std::unordered_set<uint64_t> log_recycle_files_set(
431 state.log_recycle_files.begin(), state.log_recycle_files.end());
432 std::unordered_set<uint64_t> quarantine_files_set(
433 state.files_to_quarantine.begin(), state.files_to_quarantine.end());
434
435 auto candidate_files = state.full_scan_candidate_files;
436 candidate_files.reserve(
437 candidate_files.size() + state.sst_delete_files.size() +
438 state.blob_delete_files.size() + state.log_delete_files.size() +
439 state.manifest_delete_files.size());
440 // We may ignore the dbname when generating the file names.
441 for (auto& file : state.sst_delete_files) {
442 auto* handle = file.metadata->table_reader_handle;
443 if (file.only_delete_metadata) {
444 if (handle) {
445 // Simply release handle of file that is not being deleted
446 table_cache_->Release(handle);
447 }
448 } else {
449 // File is being deleted (actually obsolete)
450 auto number = file.metadata->fd.GetNumber();
451 candidate_files.emplace_back(MakeTableFileName(number), file.path);
452 TableCache::ReleaseObsolete(table_cache_.get(), number, handle,
453 file.uncache_aggressiveness);
454 }
455 file.DeleteMetadata();
456 }
457
458 for (const auto& blob_file : state.blob_delete_files) {
459 candidate_files.emplace_back(BlobFileName(blob_file.GetBlobFileNumber()),
460 blob_file.GetPath());
461 }
462
463 auto wal_dir = immutable_db_options_.GetWalDir();
464 for (auto file_num : state.log_delete_files) {
465 if (file_num > 0) {
466 candidate_files.emplace_back(LogFileName(file_num), wal_dir);
467 }
468 }
469 for (const auto& filename : state.manifest_delete_files) {
470 candidate_files.emplace_back(filename, dbname_);
471 }
472
473 // dedup state.candidate_files so we don't try to delete the same
474 // file twice
475 std::sort(candidate_files.begin(), candidate_files.end(),
476 [](const JobContext::CandidateFileInfo& lhs,
477 const JobContext::CandidateFileInfo& rhs) {
478 if (lhs.file_name < rhs.file_name) {
479 return true;
480 } else if (lhs.file_name > rhs.file_name) {
481 return false;
482 } else {
483 return (lhs.file_path < rhs.file_path);
484 }
485 });
486 candidate_files.erase(
487 std::unique(candidate_files.begin(), candidate_files.end()),
488 candidate_files.end());
489
490 if (state.prev_total_log_size > 0) {
492 "[JOB %d] Try to delete WAL files size %" PRIu64
493 ", prev total WAL file size %" PRIu64
494 ", number of live WAL files %" ROCKSDB_PRIszt ".\n",
495 state.job_id, state.size_log_to_delete,
496 state.prev_total_log_size, state.num_alive_log_files);
497 }
498
499 std::vector<std::string> old_info_log_files;
500 InfoLogPrefix info_log_prefix(!immutable_db_options_.db_log_dir.empty(),
501 dbname_);
502
503 // File numbers of most recent two OPTIONS file in candidate_files (found in
504 // previous FindObsoleteFiles(full_scan=true))
505 // At this point, there must not be any duplicate file numbers in
506 // candidate_files.
507 uint64_t optsfile_num1 = std::numeric_limits<uint64_t>::min();
508 uint64_t optsfile_num2 = std::numeric_limits<uint64_t>::min();
509 for (const auto& candidate_file : candidate_files) {
510 const std::string& fname = candidate_file.file_name;
511 uint64_t number;
513 if (!ParseFileName(fname, &number, info_log_prefix.prefix, &type) ||
514 type != kOptionsFile) {
515 continue;
516 }
517 if (number > optsfile_num1) {
518 optsfile_num2 = optsfile_num1;
519 optsfile_num1 = number;
520 } else if (number > optsfile_num2) {
521 optsfile_num2 = number;
522 }
523 }
524
525 // For remote compactions, we need to keep OPTIONS file that may get
526 // referenced by the remote worker
527
528 optsfile_num2 = std::min(optsfile_num2, state.min_options_file_number);
529
530 // Close WALs before trying to delete them.
531 for (const auto w : state.logs_to_free) {
532 // TODO: maybe check the return value of Close.
533 // TODO: plumb Env::IOActivity, Env::IOPriority
534 auto s = w->Close({});
535 s.PermitUncheckedError();
536 }
537
538 bool own_files = OwnTablesAndLogs();
539 std::unordered_set<uint64_t> files_to_del;
540 for (const auto& candidate_file : candidate_files) {
541 const std::string& to_delete = candidate_file.file_name;
542 uint64_t number;
544 // Ignore file if we cannot recognize it.
545 if (!ParseFileName(to_delete, &number, info_log_prefix.prefix, &type)) {
546 continue;
547 }
548
549 if (quarantine_files_set.find(number) != quarantine_files_set.end()) {
550 continue;
551 }
552
553 bool keep = true;
554 switch (type) {
555 case kWalFile:
556 keep = ((number >= state.log_number) ||
557 (number == state.prev_log_number) ||
558 (log_recycle_files_set.find(number) !=
559 log_recycle_files_set.end()));
560 break;
561 case kDescriptorFile:
562 // Keep my manifest file, and any newer incarnations'
563 // (can happen during manifest roll)
564 keep = (number >= state.manifest_file_number);
565 break;
566 case kTableFile:
567 // If the second condition is not there, this makes
568 // DontDeletePendingOutputs fail
569 // FIXME: but should NOT keep if it came from sst_delete_files?
570 keep = (sst_live_set.find(number) != sst_live_set.end()) ||
571 number >= state.min_pending_output;
572 if (!keep) {
573 // NOTE: sometimes redundant (if came from sst_delete_files)
574 // We don't know which column family is applicable here so we don't
575 // know what uncache_aggressiveness would be used with
576 // ReleaseObsolete(). Anyway, obsolete files ideally go into
577 // sst_delete_files for better/quicker handling, and this is just a
578 // backstop.
579 TableCache::Evict(table_cache_.get(), number);
580 files_to_del.insert(number);
581 }
582 break;
583 case kBlobFile:
584 keep = number >= state.min_pending_output ||
585 (blob_live_set.find(number) != blob_live_set.end());
586 if (!keep) {
587 files_to_del.insert(number);
588 }
589 break;
590 case kTempFile:
591 // Any temp files that are currently being written to must
592 // be recorded in pending_outputs_, which is inserted into "live".
593 // Also, SetCurrentFile creates a temp file when writing out new
594 // manifest, which is equal to state.pending_manifest_file_number. We
595 // should not delete that file
596 //
597 // TODO(yhchiang): carefully modify the third condition to safely
598 // remove the temp options files.
599 keep = (sst_live_set.find(number) != sst_live_set.end()) ||
600 (blob_live_set.find(number) != blob_live_set.end()) ||
601 (number == state.pending_manifest_file_number) ||
602 (to_delete.find(kOptionsFileNamePrefix) != std::string::npos);
603 break;
604 case kInfoLogFile:
605 keep = true;
606 if (number != 0) {
607 old_info_log_files.push_back(to_delete);
608 }
609 break;
610 case kOptionsFile:
611 keep = (number >= optsfile_num2);
612 break;
613 case kCurrentFile:
614 case kDBLockFile:
615 case kIdentityFile:
616 case kMetaDatabase:
617 keep = true;
618 break;
619 }
620
621 if (keep) {
622 continue;
623 }
624
625 std::string fname;
626 std::string dir_to_sync;
627 if (type == kTableFile) {
628 fname = MakeTableFileName(candidate_file.file_path, number);
629 dir_to_sync = candidate_file.file_path;
630 } else if (type == kBlobFile) {
631 fname = BlobFileName(candidate_file.file_path, number);
632 dir_to_sync = candidate_file.file_path;
633 } else {
634 dir_to_sync = (type == kWalFile) ? wal_dir : dbname_;
635 fname = dir_to_sync +
636 ((!dir_to_sync.empty() && dir_to_sync.back() == '/') ||
637 (!to_delete.empty() && to_delete.front() == '/')
638 ? ""
639 : "/") +
640 to_delete;
641 }
642
643 if (type == kWalFile && (immutable_db_options_.WAL_ttl_seconds > 0 ||
645 wal_manager_.ArchiveWALFile(fname, number);
646 continue;
647 }
648
649 // If I do not own these files, e.g. secondary instance with max_open_files
650 // = -1, then no need to delete or schedule delete these files since they
651 // will be removed by their owner, e.g. the primary instance.
652 if (!own_files) {
653 continue;
654 }
655 if (schedule_only) {
656 InstrumentedMutexLock guard_lock(&mutex_);
657 SchedulePendingPurge(fname, dir_to_sync, type, number, state.job_id);
658 } else {
659 DeleteObsoleteFileImpl(state.job_id, fname, dir_to_sync, type, number);
660 }
661 }
662
663 {
664 // After purging obsolete files, remove them from files_grabbed_for_purge_.
665 InstrumentedMutexLock guard_lock(&mutex_);
666 autovector<uint64_t> to_be_removed;
667 for (auto fn : files_grabbed_for_purge_) {
668 if (files_to_del.count(fn) != 0) {
669 to_be_removed.emplace_back(fn);
670 }
671 }
672 for (auto fn : to_be_removed) {
673 files_grabbed_for_purge_.erase(fn);
674 }
675 }
676
677 // Delete old info log files.
678 size_t old_info_log_file_count = old_info_log_files.size();
679 if (old_info_log_file_count != 0 &&
680 old_info_log_file_count >= immutable_db_options_.keep_log_file_num) {
681 std::sort(old_info_log_files.begin(), old_info_log_files.end());
682 size_t end =
683 old_info_log_file_count - immutable_db_options_.keep_log_file_num;
684 for (unsigned int i = 0; i <= end; i++) {
685 std::string& to_delete = old_info_log_files.at(i);
686 std::string full_path_to_delete =
688 ? dbname_
690 "/" + to_delete;
692 "[JOB %d] Delete info log file %s\n", state.job_id,
693 full_path_to_delete.c_str());
694 Status s = env_->DeleteFile(full_path_to_delete);
695 if (!s.ok()) {
696 if (env_->FileExists(full_path_to_delete).IsNotFound()) {
699 "[JOB %d] Tried to delete non-existing info log file %s FAILED "
700 "-- %s\n",
701 state.job_id, to_delete.c_str(), s.ToString().c_str());
702 } else {
704 "[JOB %d] Delete info log file %s FAILED -- %s\n",
705 state.job_id, to_delete.c_str(),
706 s.ToString().c_str());
707 }
708 }
709 }
710 }
713 InstrumentedMutexLock l(&mutex_);
715 assert(pending_purge_obsolete_files_ >= 0);
716 if (schedule_only) {
717 // Must change from pending_purge_obsolete_files_ to bg_purge_scheduled_
718 // while holding mutex (for GetSortedWalFiles() etc.)
720 }
721 if (pending_purge_obsolete_files_ == 0) {
723 }
724 TEST_SYNC_POINT("DBImpl::PurgeObsoleteFiles:End");
725}
virtual bool OwnTablesAndLogs() const
Definition db_impl.h:1621
void SchedulePendingPurge(std::string fname, std::string dir_to_sync, FileType type, uint64_t number, int job_id)
void ArchiveWALFile(const std::string &fname, uint64_t number)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Put() [1/4]

Status ROCKSDB_NAMESPACE::DBImpl::Put ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const Slice & ts,
const Slice & value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 32 번째 라인에서 정의되었습니다.

33 {
34 const Status s = FailIfTsMismatchCf(column_family, ts);
35 if (!s.ok()) {
36 return s;
37 }
38 return DB::Put(o, column_family, key, ts, val);
39}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ Put() [2/4]

Status ROCKSDB_NAMESPACE::DBImpl::Put ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const Slice & value )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 23 번째 라인에서 정의되었습니다.

24 {
25 const Status s = FailIfCfHasTs(column_family);
26 if (!s.ok()) {
27 return s;
28 }
29 return DB::Put(o, column_family, key, val);
30}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Put() [3/4]

virtual Status ROCKSDB_NAMESPACE::DB::Put ( const WriteOptions & options,
const Slice & key,
const Slice & ts,
const Slice & value )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 466 번째 라인에서 정의되었습니다.

467 {
468 return Put(options, DefaultColumnFamily(), key, ts, value);
469 }
Status Put(const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key, const Slice &value) override

◆ Put() [4/4]

virtual Status ROCKSDB_NAMESPACE::DB::Put ( const WriteOptions & options,
const Slice & key,
const Slice & value )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 462 번째 라인에서 정의되었습니다.

463 {
464 return Put(options, DefaultColumnFamily(), key, value);
465 }

◆ PutEntity() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::PutEntity ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const WideColumns & columns )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 41 번째 라인에서 정의되었습니다.

43 {
44 const Status s = FailIfCfHasTs(column_family);
45 if (!s.ok()) {
46 return s;
47 }
48
49 return DB::PutEntity(options, column_family, key, columns);
50}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PutEntity() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::PutEntity ( const WriteOptions & options,
const Slice & key,
const AttributeGroups & attribute_groups )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 52 번째 라인에서 정의되었습니다.

53 {
54 for (const AttributeGroup& ag : attribute_groups) {
55 const Status s = FailIfCfHasTs(ag.column_family());
56 if (!s.ok()) {
57 return s;
58 }
59 }
60 return DB::PutEntity(options, key, attribute_groups);
61}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ RecordSeqnoToTimeMapping()

void ROCKSDB_NAMESPACE::DBImpl::RecordSeqnoToTimeMapping ( uint64_t populate_historical_seconds)

db_impl.cc 파일의 6804 번째 라인에서 정의되었습니다.

6804 {
6805 // TECHNICALITY: Sample last sequence number *before* time, as prescribed
6806 // for SeqnoToTimeMapping. We don't know how long it has been since the last
6807 // sequence number was written, so we at least have a one-sided bound by
6808 // sampling in this order.
6810 int64_t unix_time_signed = 0;
6811 immutable_db_options_.clock->GetCurrentTime(&unix_time_signed)
6812 .PermitUncheckedError(); // Ignore error
6813 uint64_t unix_time = static_cast<uint64_t>(unix_time_signed);
6814
6815 std::vector<SuperVersionContext> sv_contexts;
6816 if (populate_historical_seconds > 0) {
6817 bool success = true;
6818 {
6819 InstrumentedMutexLock l(&mutex_);
6820 if (seqno > 1 && unix_time > populate_historical_seconds) {
6821 // seqno=0 is reserved
6822 SequenceNumber from_seqno = 1;
6824 from_seqno, seqno, unix_time - populate_historical_seconds,
6825 unix_time);
6826 InstallSeqnoToTimeMappingInSV(&sv_contexts);
6827 } else {
6828 // One of these will fail
6829 assert(seqno > 1);
6830 assert(unix_time > populate_historical_seconds);
6831 success = false;
6832 }
6833 }
6834 if (success) {
6837 "Pre-populated sequence number to time entries: [1,%" PRIu64
6838 "] -> [%" PRIu64 ",%" PRIu64 "]",
6839 seqno, unix_time - populate_historical_seconds, unix_time);
6840 } else {
6843 "Failed to pre-populate sequence number to time entries: [1,%" PRIu64
6844 "] -> [%" PRIu64 ",%" PRIu64 "]",
6845 seqno, unix_time - populate_historical_seconds, unix_time);
6846 }
6847 } else {
6848 InstrumentedMutexLock l(&mutex_);
6849 // FIXME: assert(seqno > 0);
6850 // Always successful assuming seqno never go backwards
6851 seqno_to_time_mapping_.Append(seqno, unix_time);
6852 InstallSeqnoToTimeMappingInSV(&sv_contexts);
6853 }
6854
6855 // clean up outside db mutex
6856 for (SuperVersionContext& sv_context : sv_contexts) {
6857 sv_context.Clean();
6858 }
6859}
SeqnoToTimeMapping seqno_to_time_mapping_
Definition db_impl.h:3015
void InstallSeqnoToTimeMappingInSV(std::vector< SuperVersionContext > *sv_contexts)
Definition db_impl.cc:6917
SequenceNumber GetLatestSequenceNumber() const override
Definition db_impl.cc:1901
bool Append(SequenceNumber seqno, uint64_t time)
bool PrePopulate(SequenceNumber from_seqno, SequenceNumber to_seqno, uint64_t from_time, uint64_t to_time)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Recover()

Status ROCKSDB_NAMESPACE::DBImpl::Recover ( const std::vector< ColumnFamilyDescriptor > & column_families,
bool read_only = false,
bool error_if_wal_file_exists = false,
bool error_if_data_exists_in_wals = false,
bool is_retry = false,
uint64_t * recovered_seq = nullptr,
RecoveryContext * recovery_ctx = nullptr,
bool * can_retry = nullptr )
protectedvirtual

ROCKSDB_NAMESPACE::DBImplFollower, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_open.cc 파일의 412 번째 라인에서 정의되었습니다.

416 {
417 mutex_.AssertHeld();
418
419 const WriteOptions write_options(Env::IOActivity::kDBOpen);
420 bool tmp_is_new_db = false;
421 bool& is_new_db = recovery_ctx ? recovery_ctx->is_new_db_ : tmp_is_new_db;
422 assert(db_lock_ == nullptr);
423 std::vector<std::string> files_in_dbname;
424 if (!read_only) {
425 Status s = directories_.SetDirectories(fs_.get(), dbname_,
428 if (!s.ok()) {
429 return s;
430 }
431
432 s = env_->LockFile(LockFileName(dbname_), &db_lock_);
433 if (!s.ok()) {
434 return s;
435 }
436
437 std::string current_fname = CurrentFileName(dbname_);
438 // Path to any MANIFEST file in the db dir. It does not matter which one.
439 // Since best-efforts recovery ignores CURRENT file, existence of a
440 // MANIFEST indicates the recovery to recover existing db. If no MANIFEST
441 // can be found, a new db will be created.
442 std::string manifest_path;
444 s = env_->FileExists(current_fname);
445 } else {
446 s = Status::NotFound();
447 IOOptions io_opts;
448 io_opts.do_not_recurse = true;
449 Status io_s = immutable_db_options_.fs->GetChildren(
450 dbname_, io_opts, &files_in_dbname, /*IODebugContext*=*/nullptr);
451 if (!io_s.ok()) {
452 s = io_s;
453 files_in_dbname.clear();
454 }
455 for (const std::string& file : files_in_dbname) {
456 uint64_t number = 0;
457 FileType type = kWalFile; // initialize
458 if (ParseFileName(file, &number, &type) && type == kDescriptorFile) {
459 uint64_t bytes;
460 s = env_->GetFileSize(DescriptorFileName(dbname_, number), &bytes);
461 if (s.ok() && bytes != 0) {
462 // Found non-empty MANIFEST (descriptor log), thus best-efforts
463 // recovery does not have to treat the db as empty.
464 manifest_path = dbname_ + "/" + file;
465 break;
466 }
467 }
468 }
469 }
470 if (s.IsNotFound()) {
472 s = NewDB(&files_in_dbname);
473 is_new_db = true;
474 if (!s.ok()) {
475 return s;
476 }
477 } else {
478 return Status::InvalidArgument(
479 current_fname, "does not exist (create_if_missing is false)");
480 }
481 } else if (s.ok()) {
483 return Status::InvalidArgument(dbname_,
484 "exists (error_if_exists is true)");
485 }
486 } else {
487 // Unexpected error reading file
488 assert(s.IsIOError());
489 return s;
490 }
491 // Verify compatibility of file_options_ and filesystem
492 {
493 std::unique_ptr<FSRandomAccessFile> idfile;
494 FileOptions customized_fs(file_options_);
495 customized_fs.use_direct_reads |=
497 const std::string& fname =
498 manifest_path.empty() ? current_fname : manifest_path;
499 s = fs_->NewRandomAccessFile(fname, customized_fs, &idfile, nullptr);
500 if (!s.ok()) {
501 std::string error_str = s.ToString();
502 // Check if unsupported Direct I/O is the root cause
503 customized_fs.use_direct_reads = false;
504 s = fs_->NewRandomAccessFile(fname, customized_fs, &idfile, nullptr);
505 if (s.ok()) {
506 return Status::InvalidArgument(
507 "Direct I/O is not supported by the specified DB.");
508 } else {
509 return Status::InvalidArgument(
510 "Found options incompatible with filesystem", error_str.c_str());
511 }
512 }
513 }
515 assert(files_in_dbname.empty());
516 IOOptions io_opts;
517 io_opts.do_not_recurse = true;
518 Status s = immutable_db_options_.fs->GetChildren(
519 dbname_, io_opts, &files_in_dbname, /*IODebugContext*=*/nullptr);
520 if (s.IsNotFound()) {
521 return Status::InvalidArgument(dbname_,
522 "does not exist (open for read only)");
523 } else if (s.IsIOError()) {
524 return s;
525 }
526 assert(s.ok());
527 }
528 assert(is_new_db || db_id_.empty());
529 Status s;
530 bool missing_table_file = false;
532 // Status of reading the descriptor file
533 Status desc_status;
534 s = versions_->Recover(column_families, read_only, &db_id_,
535 /*no_error_if_files_missing=*/false, is_retry,
536 &desc_status);
537 desc_status.PermitUncheckedError();
538 if (is_retry) {
539 RecordTick(stats_, FILE_READ_CORRUPTION_RETRY_COUNT);
540 if (desc_status.ok()) {
541 RecordTick(stats_, FILE_READ_CORRUPTION_RETRY_SUCCESS_COUNT);
542 }
543 }
544 if (can_retry) {
545 // If we're opening for the first time and the failure is likely due to
546 // a corrupt MANIFEST file (could result in either the log::Reader
547 // detecting a corrupt record, or SST files not found error due to
548 // discarding badly formed tail records)
549 if (!is_retry &&
550 (desc_status.IsCorruption() || s.IsNotFound() || s.IsCorruption()) &&
552 FSSupportedOps::kVerifyAndReconstructRead)) {
553 *can_retry = true;
556 "Possible corruption detected while replaying MANIFEST %s, %s. "
557 "Will be retried.",
558 desc_status.ToString().c_str(), s.ToString().c_str());
559 } else {
560 *can_retry = false;
561 }
562 }
563 } else {
564 assert(!files_in_dbname.empty());
565 s = versions_->TryRecover(column_families, read_only, files_in_dbname,
566 &db_id_, &missing_table_file);
567 if (s.ok()) {
568 // TryRecover may delete previous column_family_set_.
570 new ColumnFamilyMemTablesImpl(versions_->GetColumnFamilySet()));
571 }
572 }
573 if (!s.ok()) {
574 return s;
575 }
576 if (s.ok() && !read_only) {
577 for (auto cfd : *versions_->GetColumnFamilySet()) {
578 auto& moptions = *cfd->GetLatestMutableCFOptions();
579 // Try to trivially move files down the LSM tree to start from bottommost
580 // level when level_compaction_dynamic_level_bytes is enabled. This should
581 // only be useful when user is migrating to turning on this option.
582 // If a user is migrating from Level Compaction with a smaller level
583 // multiplier or from Universal Compaction, there may be too many
584 // non-empty levels and the trivial moves here are not sufficed for
585 // migration. Additional compactions are needed to drain unnecessary
586 // levels.
587 //
588 // Note that this step moves files down LSM without consulting
589 // SSTPartitioner. Further compactions are still needed if
590 // the user wants to partition SST files.
591 // Note that files moved in this step may not respect the compression
592 // option in target level.
593 if (cfd->ioptions()->compaction_style ==
594 CompactionStyle::kCompactionStyleLevel &&
595 cfd->ioptions()->level_compaction_dynamic_level_bytes &&
596 !moptions.disable_auto_compactions) {
597 int to_level = cfd->ioptions()->num_levels - 1;
598 // last level is reserved
599 // allow_ingest_behind does not support Level Compaction,
600 // and per_key_placement can have infinite compaction loop for Level
601 // Compaction. Adjust to_level here just to be safe.
602 if (cfd->ioptions()->allow_ingest_behind ||
603 moptions.preclude_last_level_data_seconds > 0) {
604 to_level -= 1;
605 }
606 // Whether this column family has a level trivially moved
607 bool moved = false;
608 // Fill the LSM starting from to_level and going up one level at a time.
609 // Some loop invariants (when last level is not reserved):
610 // - levels in (from_level, to_level] are empty, and
611 // - levels in (to_level, last_level] are non-empty.
612 for (int from_level = to_level; from_level >= 0; --from_level) {
613 const std::vector<FileMetaData*>& level_files =
614 cfd->current()->storage_info()->LevelFiles(from_level);
615 if (level_files.empty() || from_level == 0) {
616 continue;
617 }
618 assert(from_level <= to_level);
619 // Trivial move files from `from_level` to `to_level`
620 if (from_level < to_level) {
621 if (!moved) {
622 // lsm_state will look like "[1,2,3,4,5,6,0]" for an LSM with
623 // 7 levels
624 std::string lsm_state = "[";
625 for (int i = 0; i < cfd->ioptions()->num_levels; ++i) {
626 lsm_state += std::to_string(
627 cfd->current()->storage_info()->NumLevelFiles(i));
628 if (i < cfd->ioptions()->num_levels - 1) {
629 lsm_state += ",";
630 }
631 }
632 lsm_state += "]";
634 "[%s] Trivially move files down the LSM when open "
635 "with level_compaction_dynamic_level_bytes=true,"
636 " lsm_state: %s (Files are moved only if DB "
637 "Recovery is successful).",
638 cfd->GetName().c_str(), lsm_state.c_str());
639 moved = true;
640 }
643 "[%s] Moving %zu files from from_level-%d to from_level-%d",
644 cfd->GetName().c_str(), level_files.size(), from_level,
645 to_level);
646 VersionEdit edit;
647 edit.SetColumnFamily(cfd->GetID());
648 for (const FileMetaData* f : level_files) {
649 edit.DeleteFile(from_level, f->fd.GetNumber());
650 edit.AddFile(to_level, f->fd.GetNumber(), f->fd.GetPathId(),
651 f->fd.GetFileSize(), f->smallest, f->largest,
652 f->fd.smallest_seqno, f->fd.largest_seqno,
653 f->marked_for_compaction,
654 f->temperature, // this can be different from
655 // `last_level_temperature`
656 f->oldest_blob_file_number, f->oldest_ancester_time,
657 f->file_creation_time, f->epoch_number,
658 f->file_checksum, f->file_checksum_func_name,
659 f->unique_id, f->compensated_range_deletion_size,
660 f->tail_size, f->user_defined_timestamps_persisted);
662 "[%s] Moving #%" PRIu64
663 " from from_level-%d to from_level-%d %" PRIu64
664 " bytes\n",
665 cfd->GetName().c_str(), f->fd.GetNumber(),
666 from_level, to_level, f->fd.GetFileSize());
667 }
668 recovery_ctx->UpdateVersionEdits(cfd, edit);
669 }
670 --to_level;
671 }
672 }
673 }
674 }
675 if (is_new_db) {
676 // Already set up DB ID in NewDB
677 } else if (immutable_db_options_.write_dbid_to_manifest && recovery_ctx) {
678 VersionEdit edit;
679 s = SetupDBId(write_options, read_only, is_new_db, is_retry, &edit);
680 recovery_ctx->UpdateVersionEdits(
681 versions_->GetColumnFamilySet()->GetDefault(), edit);
682 } else {
683 s = SetupDBId(write_options, read_only, is_new_db, is_retry, nullptr);
684 }
685 assert(!s.ok() || !db_id_.empty());
686 ROCKS_LOG_INFO(immutable_db_options_.info_log, "DB ID: %s\n", db_id_.c_str());
687 if (s.ok() && !read_only) {
688 s = MaybeUpdateNextFileNumber(recovery_ctx);
689 }
690
692 s = CheckConsistency();
693 }
694 if (s.ok() && !read_only) {
695 // TODO: share file descriptors (FSDirectory) with SetDirectories above
696 std::map<std::string, std::shared_ptr<FSDirectory>> created_dirs;
697 for (auto cfd : *versions_->GetColumnFamilySet()) {
698 s = cfd->AddDirectories(&created_dirs);
699 if (!s.ok()) {
700 return s;
701 }
702 }
703 }
704
705 std::vector<std::string> files_in_wal_dir;
706 if (s.ok()) {
707 // Initial max_total_in_memory_state_ before recovery wals. Log recovery
708 // may check this value to decide whether to flush.
710 for (auto cfd : *versions_->GetColumnFamilySet()) {
711 auto* mutable_cf_options = cfd->GetLatestMutableCFOptions();
712 max_total_in_memory_state_ += mutable_cf_options->write_buffer_size *
713 mutable_cf_options->max_write_buffer_number;
714 }
715
716 SequenceNumber next_sequence(kMaxSequenceNumber);
717 default_cf_handle_ = new ColumnFamilyHandleImpl(
718 versions_->GetColumnFamilySet()->GetDefault(), this, &mutex_);
720
721 // Recover from all newer log files than the ones named in the
722 // descriptor (new log files may have been added by the previous
723 // incarnation without registering them in the descriptor).
724 //
725 // Note that prev_log_number() is no longer used, but we pay
726 // attention to it in case we are recovering a database
727 // produced by an older version of rocksdb.
728 auto wal_dir = immutable_db_options_.GetWalDir();
730 IOOptions io_opts;
731 io_opts.do_not_recurse = true;
732 s = immutable_db_options_.fs->GetChildren(
733 wal_dir, io_opts, &files_in_wal_dir, /*IODebugContext*=*/nullptr);
734 }
735 if (s.IsNotFound()) {
736 return Status::InvalidArgument("wal_dir not found", wal_dir);
737 } else if (!s.ok()) {
738 return s;
739 }
740
741 std::unordered_map<uint64_t, std::string> wal_files;
742 for (const auto& file : files_in_wal_dir) {
743 uint64_t number;
745 if (ParseFileName(file, &number, &type) && type == kWalFile) {
746 if (is_new_db) {
747 return Status::Corruption(
748 "While creating a new Db, wal_dir contains "
749 "existing log file: ",
750 file);
751 } else {
752 wal_files[number] = LogFileName(wal_dir, number);
753 }
754 }
755 }
756
759 // Verify WALs in MANIFEST.
760 s = versions_->GetWalSet().CheckWals(env_, wal_files);
761 } // else since best effort recovery does not recover from WALs, no need
762 // to check WALs.
763 } else if (!versions_->GetWalSet().GetWals().empty()) {
764 // Tracking is disabled, clear previously tracked WALs from MANIFEST,
765 // otherwise, in the future, if WAL tracking is enabled again,
766 // since the WALs deleted when WAL tracking is disabled are not persisted
767 // into MANIFEST, WAL check may fail.
768 VersionEdit edit;
769 WalNumber max_wal_number =
770 versions_->GetWalSet().GetWals().rbegin()->first;
771 edit.DeleteWalsBefore(max_wal_number + 1);
772 assert(recovery_ctx != nullptr);
773 assert(versions_->GetColumnFamilySet() != nullptr);
774 recovery_ctx->UpdateVersionEdits(
775 versions_->GetColumnFamilySet()->GetDefault(), edit);
776 }
777 if (!s.ok()) {
778 return s;
779 }
780
781 if (!wal_files.empty()) {
782 if (error_if_wal_file_exists) {
783 return Status::Corruption(
784 "The db was opened in readonly mode with error_if_wal_file_exists"
785 "flag but a WAL file already exists");
786 } else if (error_if_data_exists_in_wals) {
787 for (auto& wal_file : wal_files) {
788 uint64_t bytes;
789 s = env_->GetFileSize(wal_file.second, &bytes);
790 if (s.ok()) {
791 if (bytes > 0) {
792 return Status::Corruption(
793 "error_if_data_exists_in_wals is set but there are data "
794 " in WAL files.");
795 }
796 }
797 }
798 }
799 }
800
801 if (!wal_files.empty()) {
802 // Recover in the order in which the wals were generated
803 std::vector<uint64_t> wals;
804 wals.reserve(wal_files.size());
805 for (const auto& wal_file : wal_files) {
806 wals.push_back(wal_file.first);
807 }
808 std::sort(wals.begin(), wals.end());
809
810 bool corrupted_wal_found = false;
811 s = RecoverLogFiles(wals, &next_sequence, read_only, is_retry,
812 &corrupted_wal_found, recovery_ctx);
813 if (corrupted_wal_found && recovered_seq != nullptr) {
814 *recovered_seq = next_sequence;
815 }
816 if (!s.ok()) {
817 // Clear memtables if recovery failed
818 for (auto cfd : *versions_->GetColumnFamilySet()) {
819 cfd->CreateNewMemtable(*cfd->GetLatestMutableCFOptions(),
820 kMaxSequenceNumber);
821 }
822 }
823 }
824 }
825
826 if (read_only) {
827 // If we are opening as read-only, we need to update options_file_number_
828 // to reflect the most recent OPTIONS file. It does not matter for regular
829 // read-write db instance because options_file_number_ will later be
830 // updated to versions_->NewFileNumber() in RenameTempFileToOptionsFile.
831 std::vector<std::string> filenames;
832 if (s.ok()) {
833 const std::string normalized_dbname = NormalizePath(dbname_);
834 const std::string normalized_wal_dir =
837 filenames = std::move(files_in_dbname);
838 } else if (normalized_dbname == normalized_wal_dir) {
839 filenames = std::move(files_in_wal_dir);
840 } else {
841 IOOptions io_opts;
842 io_opts.do_not_recurse = true;
843 s = immutable_db_options_.fs->GetChildren(
844 GetName(), io_opts, &filenames, /*IODebugContext*=*/nullptr);
845 }
846 }
847 if (s.ok()) {
848 uint64_t number = 0;
849 uint64_t options_file_number = 0;
851 for (const auto& fname : filenames) {
852 if (ParseFileName(fname, &number, &type) && type == kOptionsFile) {
853 options_file_number = std::max(number, options_file_number);
854 }
855 }
856 versions_->options_file_number_ = options_file_number;
857 uint64_t options_file_size = 0;
858 if (options_file_number > 0) {
859 s = env_->GetFileSize(OptionsFileName(GetName(), options_file_number),
860 &options_file_size);
861 }
862 versions_->options_file_size_ = options_file_size;
863 }
864 }
865 return s;
866}
Status MaybeUpdateNextFileNumber(RecoveryContext *recovery_ctx)
Status NewDB(std::vector< std::string > *new_filenames)
Status RecoverLogFiles(const std::vector< uint64_t > &log_numbers, SequenceNumber *next_sequence, bool read_only, bool is_retry, bool *corrupted_log_found, RecoveryContext *recovery_ctx)
virtual Status CheckConsistency()
Definition db_impl.cc:5145
IOStatus SetDirectories(FileSystem *fs, const std::string &dbname, const std::string &wal_dir, const std::vector< DbPath > &data_paths)
virtual Status LockFile(const std::string &fname, FileLock **lock)=0
std::string LockFileName(const std::string &dbname)
Definition filename.cc:181
bool CheckFSFeatureSupport(FileSystem *fs, FSSupportedOps feat)
Definition file_util.h:114
uint64_t WalNumber
Definition wal_edit.h:28
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ recovered_transactions()

std::unordered_map< std::string, RecoveredTransaction * > ROCKSDB_NAMESPACE::DBImpl::recovered_transactions ( )
inline

db_impl.h 파일의 1004 번째 라인에서 정의되었습니다.

1004 {
1006 }

◆ RecoverLogFiles()

Status ROCKSDB_NAMESPACE::DBImpl::RecoverLogFiles ( const std::vector< uint64_t > & log_numbers,
SequenceNumber * next_sequence,
bool read_only,
bool is_retry,
bool * corrupted_log_found,
RecoveryContext * recovery_ctx )
private

db_impl_open.cc 파일의 1107 번째 라인에서 정의되었습니다.

1110 {
1111 struct LogReporter : public log::Reader::Reporter {
1112 Env* env;
1113 Logger* info_log;
1114 const char* fname;
1115 Status* status; // nullptr if immutable_db_options_.paranoid_checks==false
1116 bool* old_log_record;
1117 void Corruption(size_t bytes, const Status& s) override {
1118 ROCKS_LOG_WARN(info_log, "%s%s: dropping %d bytes; %s",
1119 (status == nullptr ? "(ignoring error) " : ""), fname,
1120 static_cast<int>(bytes), s.ToString().c_str());
1121 if (status != nullptr && status->ok()) {
1122 *status = s;
1123 }
1124 }
1125
1126 void OldLogRecord(size_t bytes) override {
1127 if (old_log_record != nullptr) {
1128 *old_log_record = true;
1129 }
1130 ROCKS_LOG_WARN(info_log, "%s: dropping %d bytes; possibly recycled",
1131 fname, static_cast<int>(bytes));
1132 }
1133 };
1134
1135 mutex_.AssertHeld();
1136 Status status;
1137 bool old_log_record = false;
1138 std::unordered_map<int, VersionEdit> version_edits;
1139 // no need to refcount because iteration is under mutex
1140 for (auto cfd : *versions_->GetColumnFamilySet()) {
1141 VersionEdit edit;
1142 edit.SetColumnFamily(cfd->GetID());
1143 version_edits.insert({cfd->GetID(), edit});
1144 }
1145 int job_id = next_job_id_.fetch_add(1);
1146 {
1147 auto stream = event_logger_.Log();
1148 stream << "job" << job_id << "event"
1149 << "recovery_started";
1150 stream << "wal_files";
1151 stream.StartArray();
1152 for (auto wal_number : wal_numbers) {
1153 stream << wal_number;
1154 }
1155 stream.EndArray();
1156 }
1157
1158 // No-op for immutable_db_options_.wal_filter == nullptr.
1160
1161 bool stop_replay_by_wal_filter = false;
1162 bool stop_replay_for_corruption = false;
1163 bool flushed = false;
1164 uint64_t corrupted_wal_number = kMaxSequenceNumber;
1165 uint64_t min_wal_number = MinLogNumberToKeep();
1166 if (!allow_2pc()) {
1167 // In non-2pc mode, we skip WALs that do not back unflushed data.
1168 min_wal_number =
1169 std::max(min_wal_number, versions_->MinLogNumberWithUnflushedData());
1170 }
1171 for (auto wal_number : wal_numbers) {
1172 if (wal_number < min_wal_number) {
1174 "Skipping log #%" PRIu64
1175 " since it is older than min log to keep #%" PRIu64,
1176 wal_number, min_wal_number);
1177 continue;
1178 }
1179 // The previous incarnation may not have written any MANIFEST
1180 // records after allocating this log number. So we manually
1181 // update the file number allocation counter in VersionSet.
1182 versions_->MarkFileNumberUsed(wal_number);
1183 // Open the log file
1184 std::string fname =
1186
1188 "Recovering log #%" PRIu64 " mode %d", wal_number,
1189 static_cast<int>(immutable_db_options_.wal_recovery_mode));
1190 auto logFileDropped = [this, &fname]() {
1191 uint64_t bytes;
1192 if (env_->GetFileSize(fname, &bytes).ok()) {
1193 auto info_log = immutable_db_options_.info_log.get();
1194 ROCKS_LOG_WARN(info_log, "%s: dropping %d bytes", fname.c_str(),
1195 static_cast<int>(bytes));
1196 }
1197 };
1198 if (stop_replay_by_wal_filter) {
1199 logFileDropped();
1200 continue;
1201 }
1202
1203 std::unique_ptr<SequentialFileReader> file_reader;
1204 {
1205 std::unique_ptr<FSSequentialFile> file;
1206 status = fs_->NewSequentialFile(
1207 fname, fs_->OptimizeForLogRead(file_options_), &file, nullptr);
1208 if (!status.ok()) {
1209 MaybeIgnoreError(&status);
1210 if (!status.ok()) {
1211 return status;
1212 } else {
1213 // Fail with one log file, but that's ok.
1214 // Try next one.
1215 continue;
1216 }
1217 }
1218 file_reader.reset(new SequentialFileReader(
1220 io_tracer_, /*listeners=*/{}, /*rate_limiter=*/nullptr, is_retry));
1221 }
1222
1223 // Create the log reader.
1224 LogReporter reporter;
1225 reporter.env = env_;
1226 reporter.info_log = immutable_db_options_.info_log.get();
1227 reporter.fname = fname.c_str();
1228 reporter.old_log_record = &old_log_record;
1231 WALRecoveryMode::kSkipAnyCorruptedRecords) {
1232 reporter.status = nullptr;
1233 } else {
1234 reporter.status = &status;
1235 }
1236 // We intentially make log::Reader do checksumming even if
1237 // paranoid_checks==false so that corruptions cause entire commits
1238 // to be skipped instead of propagating bad information (like overly
1239 // large sequence numbers).
1240 log::Reader reader(immutable_db_options_.info_log, std::move(file_reader),
1241 &reporter, true /*checksum*/, wal_number);
1242
1243 // Determine if we should tolerate incomplete records at the tail end of the
1244 // Read all the records and add to a memtable
1245 std::string scratch;
1246 Slice record;
1247
1248 const UnorderedMap<uint32_t, size_t>& running_ts_sz =
1249 versions_->GetRunningColumnFamiliesTimestampSize();
1250
1251 TEST_SYNC_POINT_CALLBACK("DBImpl::RecoverLogFiles:BeforeReadWal",
1252 /*arg=*/nullptr);
1253 uint64_t record_checksum;
1254 while (!stop_replay_by_wal_filter &&
1255 reader.ReadRecord(&record, &scratch,
1257 &record_checksum) &&
1258 status.ok()) {
1259 if (record.size() < WriteBatchInternal::kHeader) {
1260 reporter.Corruption(record.size(),
1261 Status::Corruption("log record too small"));
1262 continue;
1263 }
1264 // We create a new batch and initialize with a valid prot_info_ to store
1265 // the data checksums
1266 WriteBatch batch;
1267 std::unique_ptr<WriteBatch> new_batch;
1268
1269 status = WriteBatchInternal::SetContents(&batch, record);
1270 if (!status.ok()) {
1271 return status;
1272 }
1273
1274 const UnorderedMap<uint32_t, size_t>& record_ts_sz =
1275 reader.GetRecordedTimestampSize();
1277 &batch, running_ts_sz, record_ts_sz,
1278 TimestampSizeConsistencyMode::kReconcileInconsistency, seq_per_batch_,
1279 batch_per_txn_, &new_batch);
1280 if (!status.ok()) {
1281 return status;
1282 }
1283
1284 bool batch_updated = new_batch != nullptr;
1285 WriteBatch* batch_to_use = batch_updated ? new_batch.get() : &batch;
1287 "DBImpl::RecoverLogFiles:BeforeUpdateProtectionInfo:batch",
1288 batch_to_use);
1290 "DBImpl::RecoverLogFiles:BeforeUpdateProtectionInfo:checksum",
1291 &record_checksum);
1292 status = WriteBatchInternal::UpdateProtectionInfo(
1293 batch_to_use, 8 /* bytes_per_key */,
1294 batch_updated ? nullptr : &record_checksum);
1295 if (!status.ok()) {
1296 return status;
1297 }
1298
1299 SequenceNumber sequence = WriteBatchInternal::Sequence(batch_to_use);
1300 if (sequence > kMaxSequenceNumber) {
1301 reporter.Corruption(
1302 record.size(),
1303 Status::Corruption("sequence " + std::to_string(sequence) +
1304 " is too large"));
1305 continue;
1306 }
1307
1309 WALRecoveryMode::kPointInTimeRecovery) {
1310 // In point-in-time recovery mode, if sequence id of log files are
1311 // consecutive, we continue recovery despite corruption. This could
1312 // happen when we open and write to a corrupted DB, where sequence id
1313 // will start from the last sequence id we recovered.
1314 if (sequence == *next_sequence) {
1315 stop_replay_for_corruption = false;
1316 }
1317 if (stop_replay_for_corruption) {
1318 logFileDropped();
1319 break;
1320 }
1321 }
1322
1323 // For the default case of wal_filter == nullptr, always performs no-op
1324 // and returns true.
1325 if (!InvokeWalFilterIfNeededOnWalRecord(wal_number, fname, reporter,
1326 status, stop_replay_by_wal_filter,
1327 *batch_to_use)) {
1328 continue;
1329 }
1330
1331 // If column family was not found, it might mean that the WAL write
1332 // batch references to the column family that was dropped after the
1333 // insert. We don't want to fail the whole write batch in that case --
1334 // we just ignore the update.
1335 // That's why we set ignore missing column families to true
1336 bool has_valid_writes = false;
1337 status = WriteBatchInternal::InsertInto(
1338 batch_to_use, column_family_memtables_.get(), &flush_scheduler_,
1339 &trim_history_scheduler_, true, wal_number, this,
1340 false /* concurrent_memtable_writes */, next_sequence,
1341 &has_valid_writes, seq_per_batch_, batch_per_txn_);
1342 MaybeIgnoreError(&status);
1343 if (!status.ok()) {
1344 // We are treating this as a failure while reading since we read valid
1345 // blocks that do not form coherent data
1346 reporter.Corruption(record.size(), status);
1347 continue;
1348 }
1349
1350 if (has_valid_writes && !read_only) {
1351 // we can do this because this is called before client has access to the
1352 // DB and there is only a single thread operating on DB
1353 ColumnFamilyData* cfd;
1354
1355 while ((cfd = flush_scheduler_.TakeNextColumnFamily()) != nullptr) {
1356 cfd->UnrefAndTryDelete();
1357 // If this asserts, it means that InsertInto failed in
1358 // filtering updates to already-flushed column families
1359 assert(cfd->GetLogNumber() <= wal_number);
1360 auto iter = version_edits.find(cfd->GetID());
1361 assert(iter != version_edits.end());
1362 VersionEdit* edit = &iter->second;
1363 status = WriteLevel0TableForRecovery(job_id, cfd, cfd->mem(), edit);
1364 if (!status.ok()) {
1365 // Reflect errors immediately so that conditions like full
1366 // file-systems cause the DB::Open() to fail.
1367 return status;
1368 }
1369 flushed = true;
1370
1371 cfd->CreateNewMemtable(*cfd->GetLatestMutableCFOptions(),
1372 *next_sequence - 1);
1373 }
1374 }
1375 }
1377 "Recovered to log #%" PRIu64 " seq #%" PRIu64, wal_number,
1378 *next_sequence);
1379
1380 if (!status.ok() || old_log_record) {
1381 if (status.IsNotSupported()) {
1382 // We should not treat NotSupported as corruption. It is rather a clear
1383 // sign that we are processing a WAL that is produced by an incompatible
1384 // version of the code.
1385 return status;
1386 }
1388 WALRecoveryMode::kSkipAnyCorruptedRecords) {
1389 // We should ignore all errors unconditionally
1390 status = Status::OK();
1392 WALRecoveryMode::kPointInTimeRecovery) {
1393 if (status.IsIOError()) {
1395 "IOError during point-in-time reading log #%" PRIu64
1396 " seq #%" PRIu64
1397 ". %s. This likely mean loss of synced WAL, "
1398 "thus recovery fails.",
1399 wal_number, *next_sequence,
1400 status.ToString().c_str());
1401 return status;
1402 }
1403 // We should ignore the error but not continue replaying
1404 status = Status::OK();
1405 old_log_record = false;
1406 stop_replay_for_corruption = true;
1407 corrupted_wal_number = wal_number;
1408 if (corrupted_wal_found != nullptr) {
1409 *corrupted_wal_found = true;
1410 }
1411 } else {
1413 WALRecoveryMode::kTolerateCorruptedTailRecords ||
1415 WALRecoveryMode::kAbsoluteConsistency);
1416 return status;
1417 }
1418 }
1419
1422 auto last_sequence = *next_sequence - 1;
1423 if ((*next_sequence != kMaxSequenceNumber) &&
1424 (versions_->LastSequence() <= last_sequence)) {
1425 versions_->SetLastAllocatedSequence(last_sequence);
1426 versions_->SetLastPublishedSequence(last_sequence);
1427 versions_->SetLastSequence(last_sequence);
1428 }
1429 }
1430 // Compare the corrupted log number to all columnfamily's current log number.
1431 // Abort Open() if any column family's log number is greater than
1432 // the corrupted log number, which means CF contains data beyond the point of
1433 // corruption. This could during PIT recovery when the WAL is corrupted and
1434 // some (but not all) CFs are flushed
1435 // Exclude the PIT case where no log is dropped after the corruption point.
1436 // This is to cover the case for empty wals after corrupted log, in which we
1437 // don't reset stop_replay_for_corruption.
1438 if (stop_replay_for_corruption == true &&
1440 WALRecoveryMode::kPointInTimeRecovery ||
1442 WALRecoveryMode::kTolerateCorruptedTailRecords)) {
1443 for (auto cfd : *versions_->GetColumnFamilySet()) {
1444 // One special case cause cfd->GetLogNumber() > corrupted_wal_number but
1445 // the CF is still consistent: If a new column family is created during
1446 // the flush and the WAL sync fails at the same time, the new CF points to
1447 // the new WAL but the old WAL is curropted. Since the new CF is empty, it
1448 // is still consistent. We add the check of CF sst file size to avoid the
1449 // false positive alert.
1450
1451 // Note that, the check of (cfd->GetLiveSstFilesSize() > 0) may leads to
1452 // the ignorance of a very rare inconsistency case caused in data
1453 // canclation. One CF is empty due to KV deletion. But those operations
1454 // are in the WAL. If the WAL is corrupted, the status of this CF might
1455 // not be consistent with others. However, the consistency check will be
1456 // bypassed due to empty CF.
1457 // TODO: a better and complete implementation is needed to ensure strict
1458 // consistency check in WAL recovery including hanlding the tailing
1459 // issues.
1460 if (cfd->GetLogNumber() > corrupted_wal_number &&
1461 cfd->GetLiveSstFilesSize() > 0) {
1463 "Column family inconsistency: SST file contains data"
1464 " beyond the point of corruption.");
1465 return Status::Corruption("SST file is ahead of WALs in CF " +
1466 cfd->GetName());
1467 }
1468 }
1469 }
1470
1471 // True if there's any data in the WALs; if not, we can skip re-processing
1472 // them later
1473 bool data_seen = false;
1474 if (!read_only) {
1475 // no need to refcount since client still doesn't have access
1476 // to the DB and can not drop column families while we iterate
1477 const WalNumber max_wal_number = wal_numbers.back();
1478 for (auto cfd : *versions_->GetColumnFamilySet()) {
1479 auto iter = version_edits.find(cfd->GetID());
1480 assert(iter != version_edits.end());
1481 VersionEdit* edit = &iter->second;
1482
1483 if (cfd->GetLogNumber() > max_wal_number) {
1484 // Column family cfd has already flushed the data
1485 // from all wals. Memtable has to be empty because
1486 // we filter the updates based on wal_number
1487 // (in WriteBatch::InsertInto)
1488 assert(cfd->mem()->GetFirstSequenceNumber() == 0);
1489 assert(edit->NumEntries() == 0);
1490 continue;
1491 }
1492
1494 "DBImpl::RecoverLogFiles:BeforeFlushFinalMemtable", /*arg=*/nullptr);
1495
1496 // flush the final memtable (if non-empty)
1497 if (cfd->mem()->GetFirstSequenceNumber() != 0) {
1498 // If flush happened in the middle of recovery (e.g. due to memtable
1499 // being full), we flush at the end. Otherwise we'll need to record
1500 // where we were on last flush, which make the logic complicated.
1502 status = WriteLevel0TableForRecovery(job_id, cfd, cfd->mem(), edit);
1503 if (!status.ok()) {
1504 // Recovery failed
1505 break;
1506 }
1507 flushed = true;
1508
1509 cfd->CreateNewMemtable(*cfd->GetLatestMutableCFOptions(),
1510 versions_->LastSequence());
1511 }
1512 data_seen = true;
1513 }
1514
1515 // Update the log number info in the version edit corresponding to this
1516 // column family. Note that the version edits will be written to MANIFEST
1517 // together later.
1518 // writing wal_number in the manifest means that any log file
1519 // with number strongly less than (wal_number + 1) is already
1520 // recovered and should be ignored on next reincarnation.
1521 // Since we already recovered max_wal_number, we want all wals
1522 // with numbers `<= max_wal_number` (includes this one) to be ignored
1523 if (flushed || cfd->mem()->GetFirstSequenceNumber() == 0) {
1524 edit->SetLogNumber(max_wal_number + 1);
1525 }
1526 }
1527 if (status.ok()) {
1528 // we must mark the next log number as used, even though it's
1529 // not actually used. that is because VersionSet assumes
1530 // VersionSet::next_file_number_ always to be strictly greater than any
1531 // log number
1532 versions_->MarkFileNumberUsed(max_wal_number + 1);
1533 assert(recovery_ctx != nullptr);
1534
1535 for (auto* cfd : *versions_->GetColumnFamilySet()) {
1536 auto iter = version_edits.find(cfd->GetID());
1537 assert(iter != version_edits.end());
1538 recovery_ctx->UpdateVersionEdits(cfd, iter->second);
1539 }
1540
1541 if (flushed || !data_seen) {
1542 VersionEdit wal_deletion;
1544 wal_deletion.DeleteWalsBefore(max_wal_number + 1);
1545 }
1546 if (!allow_2pc()) {
1547 // In non-2pc mode, flushing the memtables of the column families
1548 // means we can advance min_log_number_to_keep.
1549 wal_deletion.SetMinLogNumberToKeep(max_wal_number + 1);
1550 }
1551 assert(versions_->GetColumnFamilySet() != nullptr);
1552 recovery_ctx->UpdateVersionEdits(
1553 versions_->GetColumnFamilySet()->GetDefault(), wal_deletion);
1554 }
1555 }
1556 }
1557
1558 if (status.ok()) {
1559 if (data_seen && !flushed) {
1560 status = RestoreAliveLogFiles(wal_numbers);
1561 } else if (!wal_numbers.empty()) { // If there's no data in the WAL, or we
1562 // flushed all the data, still
1563 // truncate the log file. If the process goes into a crash loop before
1564 // the file is deleted, the preallocated space will never get freed.
1565 const bool truncate = !read_only;
1566 GetLogSizeAndMaybeTruncate(wal_numbers.back(), truncate, nullptr)
1568 }
1569 }
1570
1571 event_logger_.Log() << "job" << job_id << "event"
1572 << "recovery_finished";
1573
1574 return status;
1575}
void InvokeWalFilterIfNeededOnColumnFamilyToWalNumberMap()
Status WriteLevel0TableForRecovery(int job_id, ColumnFamilyData *cfd, MemTable *mem, VersionEdit *edit)
Status RestoreAliveLogFiles(const std::vector< uint64_t > &log_numbers)
Status GetLogSizeAndMaybeTruncate(uint64_t wal_number, bool truncate, LogFileNumberSize *log)
bool InvokeWalFilterIfNeededOnWalRecord(uint64_t wal_number, const std::string &wal_fname, log::Reader::Reporter &reporter, Status &status, bool &stop_replay, WriteBatch &batch)
ColumnFamilyData * TakeNextColumnFamily()
int truncate(const char *path, int64_t length)
Status HandleWriteBatchTimestampSizeDifference(const WriteBatch *batch, const UnorderedMap< uint32_t, size_t > &running_ts_sz, const UnorderedMap< uint32_t, size_t > &record_ts_sz, TimestampSizeConsistencyMode check_mode, bool seq_per_batch, bool batch_per_txn, std::unique_ptr< WriteBatch > *new_batch)
Definition udt_util.cc:348
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReFitLevel()

Status ROCKSDB_NAMESPACE::DBImpl::ReFitLevel ( ColumnFamilyData * cfd,
int level,
int target_level = -1 )
private

db_impl_compaction_flush.cc 파일의 1752 번째 라인에서 정의되었습니다.

1752 {
1753 assert(level < cfd->NumberLevels());
1754 if (target_level >= cfd->NumberLevels()) {
1755 return Status::InvalidArgument("Target level exceeds number of levels");
1756 }
1757
1758 const ReadOptions read_options(Env::IOActivity::kCompaction);
1759 const WriteOptions write_options(Env::IOActivity::kCompaction);
1760
1761 SuperVersionContext sv_context(/* create_superversion */ true);
1762
1763 InstrumentedMutexLock guard_lock(&mutex_);
1764
1765 auto* vstorage = cfd->current()->storage_info();
1766 if (vstorage->LevelFiles(level).empty()) {
1767 return Status::OK();
1768 }
1769 // only allow one thread refitting
1770 if (refitting_level_) {
1772 "[ReFitLevel] another thread is refitting");
1773 return Status::NotSupported("another thread is refitting");
1774 }
1775 refitting_level_ = true;
1776
1777 const MutableCFOptions mutable_cf_options = *cfd->GetLatestMutableCFOptions();
1778 // move to a smaller level
1779 int to_level = target_level;
1780 if (target_level < 0) {
1781 to_level = FindMinimumEmptyLevelFitting(cfd, mutable_cf_options, level);
1782 }
1783
1784 if (to_level != level) {
1785 std::vector<CompactionInputFiles> input(1);
1786 input[0].level = level;
1787 // TODO (hx235): Only refit the output files in the current manual
1788 // compaction instead of all the files in the output level
1789 for (auto& f : vstorage->LevelFiles(level)) {
1790 input[0].files.push_back(f);
1791 }
1792 InternalKey refit_level_smallest;
1793 InternalKey refit_level_largest;
1794 cfd->compaction_picker()->GetRange(input[0], &refit_level_smallest,
1795 &refit_level_largest);
1796 if (to_level > level) {
1797 if (level == 0) {
1798 refitting_level_ = false;
1799 return Status::NotSupported(
1800 "Cannot change from level 0 to other levels.");
1801 }
1802 // Check levels are empty for a trivial move
1803 for (int l = level + 1; l <= to_level; l++) {
1804 if (vstorage->NumLevelFiles(l) > 0) {
1805 refitting_level_ = false;
1806 return Status::NotSupported(
1807 "Levels between source and target are not empty for a move.");
1808 }
1809 if (cfd->RangeOverlapWithCompaction(refit_level_smallest.user_key(),
1810 refit_level_largest.user_key(),
1811 l)) {
1812 refitting_level_ = false;
1813 return Status::NotSupported(
1814 "Levels between source and target "
1815 "will have some ongoing compaction's output.");
1816 }
1817 }
1818 } else {
1819 // to_level < level
1820 if (to_level == 0 && input[0].files.size() > 1) {
1821 refitting_level_ = false;
1822 return Status::Aborted(
1823 "Moving more than 1 file from non-L0 to L0 is not allowed as it "
1824 "does not bring any benefit to read nor write throughput.");
1825 }
1826 // Check levels are empty for a trivial move
1827 for (int l = to_level; l < level; l++) {
1828 if (vstorage->NumLevelFiles(l) > 0) {
1829 refitting_level_ = false;
1830 return Status::NotSupported(
1831 "Levels between source and target are not empty for a move.");
1832 }
1833 if (cfd->RangeOverlapWithCompaction(refit_level_smallest.user_key(),
1834 refit_level_largest.user_key(),
1835 l)) {
1836 refitting_level_ = false;
1837 return Status::NotSupported(
1838 "Levels between source and target "
1839 "will have some ongoing compaction's output.");
1840 }
1841 }
1842 }
1844 "[%s] Before refitting:\n%s", cfd->GetName().c_str(),
1845 cfd->current()->DebugString().data());
1846
1847 std::unique_ptr<Compaction> c(new Compaction(
1848 vstorage, *cfd->ioptions(), mutable_cf_options, mutable_db_options_,
1849 {input}, to_level,
1851 mutable_cf_options, to_level,
1852 cfd->ioptions()
1853 ->compaction_style) /* output file size limit, not applicable */
1854 ,
1855 LLONG_MAX /* max compaction bytes, not applicable */,
1856 0 /* output path ID, not applicable */, mutable_cf_options.compression,
1857 mutable_cf_options.compression_opts,
1858 mutable_cf_options.default_write_temperature,
1859 0 /* max_subcompactions, not applicable */,
1860 {} /* grandparents, not applicable */,
1861 std::nullopt /* earliest_snapshot */, nullptr /* snapshot_checker */,
1862 false /* is manual */, "" /* trim_ts */, -1 /* score, not applicable */,
1863 false /* is deletion compaction, not applicable */,
1864 false /* l0_files_might_overlap, not applicable */,
1865 CompactionReason::kRefitLevel));
1866 cfd->compaction_picker()->RegisterCompaction(c.get());
1867 TEST_SYNC_POINT("DBImpl::ReFitLevel:PostRegisterCompaction");
1868 VersionEdit edit;
1869 edit.SetColumnFamily(cfd->GetID());
1870
1871 for (const auto& f : vstorage->LevelFiles(level)) {
1872 edit.DeleteFile(level, f->fd.GetNumber());
1873 edit.AddFile(
1874 to_level, f->fd.GetNumber(), f->fd.GetPathId(), f->fd.GetFileSize(),
1875 f->smallest, f->largest, f->fd.smallest_seqno, f->fd.largest_seqno,
1876 f->marked_for_compaction, f->temperature, f->oldest_blob_file_number,
1877 f->oldest_ancester_time, f->file_creation_time, f->epoch_number,
1878 f->file_checksum, f->file_checksum_func_name, f->unique_id,
1879 f->compensated_range_deletion_size, f->tail_size,
1880 f->user_defined_timestamps_persisted);
1881 }
1883 "[%s] Apply version edit:\n%s", cfd->GetName().c_str(),
1884 edit.DebugString().data());
1885
1886 Status status = versions_->LogAndApply(cfd, mutable_cf_options,
1887 read_options, write_options, &edit,
1888 &mutex_, directories_.GetDbDir());
1889 c->MarkFilesBeingCompacted(false);
1890 cfd->compaction_picker()->UnregisterCompaction(c.get());
1891 c.reset();
1892
1893 InstallSuperVersionAndScheduleWork(cfd, &sv_context, mutable_cf_options);
1894
1895 ROCKS_LOG_DEBUG(immutable_db_options_.info_log, "[%s] LogAndApply: %s\n",
1896 cfd->GetName().c_str(), status.ToString().data());
1897
1898 if (status.ok()) {
1900 "[%s] After refitting:\n%s", cfd->GetName().c_str(),
1901 cfd->current()->DebugString().data());
1902 }
1903 sv_context.Clean();
1904 refitting_level_ = false;
1905
1906 return status;
1907 }
1908
1909 refitting_level_ = false;
1910 return Status::OK();
1911}
int FindMinimumEmptyLevelFitting(ColumnFamilyData *cfd, const MutableCFOptions &mutable_cf_options, int level)
Definition db_impl.cc:1526
uint64_t MaxFileSizeForLevel(const MutableCFOptions &cf_options, int level, CompactionStyle compaction_style, int base_level, bool level_compaction_dynamic_level_bytes)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RegisterRecordSeqnoTimeWorker()

Status ROCKSDB_NAMESPACE::DBImpl::RegisterRecordSeqnoTimeWorker ( const ReadOptions & read_options,
const WriteOptions & write_options,
bool is_new_db )
private

db_impl.cc 파일의 843 번째 라인에서 정의되었습니다.

845 {
847
848 uint64_t min_preserve_seconds = std::numeric_limits<uint64_t>::max();
849 uint64_t max_preserve_seconds = std::numeric_limits<uint64_t>::min();
850 std::vector<SuperVersionContext> sv_contexts;
851 {
852 InstrumentedMutexLock l(&mutex_);
853
854 for (auto cfd : *versions_->GetColumnFamilySet()) {
855 auto& mopts = *cfd->GetLatestMutableCFOptions();
856 // preserve time is the max of 2 options.
857 uint64_t preserve_seconds =
858 std::max(mopts.preserve_internal_time_seconds,
859 mopts.preclude_last_level_data_seconds);
860 if (!cfd->IsDropped() && preserve_seconds > 0) {
861 min_preserve_seconds = std::min(preserve_seconds, min_preserve_seconds);
862 max_preserve_seconds = std::max(preserve_seconds, max_preserve_seconds);
863 }
864 }
865 size_t old_mapping_size = seqno_to_time_mapping_.Size();
866 if (min_preserve_seconds == std::numeric_limits<uint64_t>::max()) {
867 // Don't track
870 } else {
871 uint64_t cap = std::min(kMaxSeqnoToTimeEntries,
872 max_preserve_seconds * kMaxSeqnoTimePairsPerCF /
873 min_preserve_seconds);
875 seqno_to_time_mapping_.SetMaxTimeSpan(max_preserve_seconds);
876 }
877 if (old_mapping_size != seqno_to_time_mapping_.Size()) {
878 InstallSeqnoToTimeMappingInSV(&sv_contexts);
879 }
880 }
881
882 // clean up outside db mutex
883 for (SuperVersionContext& sv_context : sv_contexts) {
884 sv_context.Clean();
885 }
886 sv_contexts.clear();
887
888 uint64_t seqno_time_cadence = 0;
889 if (min_preserve_seconds != std::numeric_limits<uint64_t>::max()) {
890 // round up to 1 when the time_duration is smaller than
891 // kMaxSeqnoTimePairsPerCF
892 seqno_time_cadence = (min_preserve_seconds + kMaxSeqnoTimePairsPerCF - 1) /
893 kMaxSeqnoTimePairsPerCF;
894 }
895
897 "DBImpl::RegisterRecordSeqnoTimeWorker:BeforePeriodicTaskType", nullptr);
898
899 Status s;
900 if (seqno_time_cadence == 0) {
901 s = periodic_task_scheduler_.Unregister(PeriodicTaskType::kRecordSeqnoTime);
902 } else {
903 // Before registering the periodic task, we need to be sure to fulfill two
904 // promises:
905 // 1) Any DB created with preserve/preclude options set from the beginning
906 // will get pre-allocated seqnos with pre-populated time mappings back to
907 // the times we are interested in. (This will enable future import of data
908 // while preserving rough write time. We can only do this reliably from
909 // DB::Open, as otherwise there could be a race between CreateColumnFamily
910 // and the first Write to the DB, and seqno-to-time mappings need to be
911 // monotonic.
912 // 2) In any DB, any data written after setting preserve/preclude options
913 // must have a reasonable time estimate (so that we can accurately place
914 // the data), which means at least one entry in seqno_to_time_mapping_.
915 //
916 // FIXME: We don't currently guarantee that if the first column family with
917 // that setting is added or configured after initial DB::Open but before
918 // the first user Write. Fixing this causes complications with the crash
919 // test because if DB starts without preserve/preclude option, does some
920 // user writes but all those writes are lost in crash, then re-opens with
921 // preserve/preclude option, it sees seqno==1 which looks like one of the
922 // user writes was recovered, when actually it was not.
923 bool last_seqno_zero = GetLatestSequenceNumber() == 0;
924 assert(!is_new_db || last_seqno_zero);
925 if (is_new_db && last_seqno_zero) {
926 // Pre-allocate seqnos and pre-populate historical mapping
927 // We can simply modify these, before writes are allowed
928 constexpr uint64_t kMax = kMaxSeqnoTimePairsPerSST;
929 versions_->SetLastAllocatedSequence(kMax);
930 versions_->SetLastPublishedSequence(kMax);
931 versions_->SetLastSequence(kMax);
932
933 // And record in manifest, to avoid going backwards in seqno on re-open
934 // (potentially with different options). Concurrency is simple because we
935 // are in DB::Open
936 {
937 InstrumentedMutexLock l(&mutex_);
938 VersionEdit edit;
939 edit.SetLastSequence(kMax);
940 s = versions_->LogAndApplyToDefaultColumnFamily(
941 read_options, write_options, &edit, &mutex_,
943 if (!s.ok() && versions_->io_status().IsIOError()) {
945 BackgroundErrorReason::kManifestWrite);
946 }
947 }
948
949 // Pre-populate mappings for reserved sequence numbers.
950 RecordSeqnoToTimeMapping(max_preserve_seconds);
951 } else {
952 if (!last_seqno_zero) {
953 // Ensure at least one mapping (or log a warning), and
954 // an updated entry whenever relevant SetOptions is called
955 RecordSeqnoToTimeMapping(/*populate_historical_seconds=*/0);
956 } else {
957 // FIXME (see limitation described above)
958 }
959 }
960
962 PeriodicTaskType::kRecordSeqnoTime,
963 periodic_task_functions_.at(PeriodicTaskType::kRecordSeqnoTime),
964 seqno_time_cadence);
965 }
966
967 return s;
968}
Status Register(PeriodicTaskType task_type, const PeriodicTaskFunc &fn)
SeqnoToTimeMapping & SetMaxTimeSpan(uint64_t max_time_span)
SeqnoToTimeMapping & SetCapacity(uint64_t capacity)
constexpr uint64_t kMaxSeqnoTimePairsPerSST
constexpr uint64_t kMaxSeqnoTimePairsPerCF
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReleaseFileNumberFromPendingOutputs()

void ROCKSDB_NAMESPACE::DBImpl::ReleaseFileNumberFromPendingOutputs ( std::unique_ptr< std::list< uint64_t >::iterator > & v)
private

db_impl.cc 파일의 4840 번째 라인에서 정의되었습니다.

4841 {
4842 if (v.get() != nullptr) {
4843 pending_outputs_.erase(*v.get());
4844 v.reset();
4845 }
4846}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReleaseOptionsFileNumber()

void ROCKSDB_NAMESPACE::DBImpl::ReleaseOptionsFileNumber ( std::unique_ptr< std::list< uint64_t >::iterator > & v)
private

db_impl.cc 파일의 4858 번째 라인에서 정의되었습니다.

4859 {
4860 if (v.get() != nullptr) {
4861 min_options_file_numbers_.erase(*v.get());
4862 v.reset();
4863 }
4864}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReleaseSnapshot()

void ROCKSDB_NAMESPACE::DBImpl::ReleaseSnapshot ( const Snapshot * snapshot)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 4327 번째 라인에서 정의되었습니다.

4327 {
4328 if (s == nullptr) {
4329 // DBImpl::GetSnapshot() can return nullptr when snapshot
4330 // not supported by specifying the condition:
4331 // inplace_update_support enabled.
4332 return;
4333 }
4334 const SnapshotImpl* casted_s = static_cast<const SnapshotImpl*>(s);
4335 {
4336 InstrumentedMutexLock l(&mutex_);
4337 snapshots_.Delete(casted_s);
4338 uint64_t oldest_snapshot;
4339 if (snapshots_.empty()) {
4340 oldest_snapshot = GetLastPublishedSequence();
4341 } else {
4342 oldest_snapshot = snapshots_.oldest()->number_;
4343 }
4344 // Avoid to go through every column family by checking a global threshold
4345 // first.
4346 CfdList cf_scheduled;
4347 if (oldest_snapshot > bottommost_files_mark_threshold_) {
4348 for (auto* cfd : *versions_->GetColumnFamilySet()) {
4349 if (!cfd->ioptions()->allow_ingest_behind) {
4350 cfd->current()->storage_info()->UpdateOldestSnapshot(
4351 oldest_snapshot, /*allow_ingest_behind=*/false);
4352 if (!cfd->current()
4353 ->storage_info()
4354 ->BottommostFilesMarkedForCompaction()
4355 .empty()) {
4358 cf_scheduled.push_back(cfd);
4359 }
4360 }
4361 }
4362
4363 // Calculate a new threshold, skipping those CFs where compactions are
4364 // scheduled. We do not do the same pass as the previous loop because
4365 // mutex might be unlocked during the loop, making the result
4366 // inaccurate.
4367 SequenceNumber new_bottommost_files_mark_threshold = kMaxSequenceNumber;
4368 for (auto* cfd : *versions_->GetColumnFamilySet()) {
4369 if (CfdListContains(cf_scheduled, cfd) ||
4370 cfd->ioptions()->allow_ingest_behind) {
4371 continue;
4372 }
4373 new_bottommost_files_mark_threshold = std::min(
4374 new_bottommost_files_mark_threshold,
4375 cfd->current()->storage_info()->bottommost_files_mark_threshold());
4376 }
4377 bottommost_files_mark_threshold_ = new_bottommost_files_mark_threshold;
4378 }
4379
4380 // Avoid to go through every column family by checking a global threshold
4381 // first.
4382 if (oldest_snapshot >= standalone_range_deletion_files_mark_threshold_) {
4383 for (auto* cfd : *versions_->GetColumnFamilySet()) {
4384 if (cfd->IsDropped() || CfdListContains(cf_scheduled, cfd)) {
4385 continue;
4386 }
4387 if (oldest_snapshot >=
4388 cfd->current()
4389 ->storage_info()
4390 ->standalone_range_tombstone_files_mark_threshold()) {
4393 cf_scheduled.push_back(cfd);
4394 }
4395 }
4396 }
4397 }
4398 delete casted_s;
4399}
SnapshotImpl * oldest() const
void Delete(const SnapshotImpl *s)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReleaseTimestampedSnapshotsOlderThan()

void ROCKSDB_NAMESPACE::DBImpl::ReleaseTimestampedSnapshotsOlderThan ( uint64_t ts,
size_t * remaining_total_ss = nullptr )

db_impl.cc 파일의 4149 번째 라인에서 정의되었습니다.

4150 {
4151 autovector<std::shared_ptr<const SnapshotImpl>> snapshots_to_release;
4152 {
4153 InstrumentedMutexLock lock_guard(&mutex_);
4154 timestamped_snapshots_.ReleaseSnapshotsOlderThan(ts, snapshots_to_release);
4155 }
4156 snapshots_to_release.clear();
4157
4158 if (remaining_total_ss) {
4159 InstrumentedMutexLock lock_guard(&mutex_);
4160 *remaining_total_ss = static_cast<size_t>(snapshots_.count());
4161 }
4162}
void ReleaseSnapshotsOlderThan(uint64_t ts, autovector< std::shared_ptr< const SnapshotImpl > > &snapshots_to_release)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RemoveManualCompaction()

void ROCKSDB_NAMESPACE::DBImpl::RemoveManualCompaction ( DBImpl::ManualCompactionState * m)
private

db_impl_compaction_flush.cc 파일의 4105 번째 라인에서 정의되었습니다.

4105 {
4106 // Remove from queue
4107 std::deque<ManualCompactionState*>::iterator it =
4109 while (it != manual_compaction_dequeue_.end()) {
4110 if (m == (*it)) {
4111 it = manual_compaction_dequeue_.erase(it);
4112 return;
4113 }
4114 ++it;
4115 }
4116 assert(false);
4117}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RenameTempFileToOptionsFile()

Status ROCKSDB_NAMESPACE::DBImpl::RenameTempFileToOptionsFile ( const std::string & file_name,
bool is_remote_compaction_enabled )
protected

db_impl.cc 파일의 5623 번째 라인에서 정의되었습니다.

5624 {
5625 Status s;
5626
5627 uint64_t options_file_number = versions_->NewFileNumber();
5628 std::string options_file_name =
5629 OptionsFileName(GetName(), options_file_number);
5630 uint64_t options_file_size = 0;
5631 s = GetEnv()->GetFileSize(file_name, &options_file_size);
5632 if (s.ok()) {
5633 // Retry if the file name happen to conflict with an existing one.
5634 s = GetEnv()->RenameFile(file_name, options_file_name);
5635 std::unique_ptr<FSDirectory> dir_obj;
5636 if (s.ok()) {
5637 s = fs_->NewDirectory(GetName(), IOOptions(), &dir_obj, nullptr);
5638 }
5639 if (s.ok()) {
5640 s = dir_obj->FsyncWithDirOptions(IOOptions(), nullptr,
5641 DirFsyncOptions(options_file_name));
5642 }
5643 if (s.ok()) {
5644 Status temp_s = dir_obj->Close(IOOptions(), nullptr);
5645 // The default Close() could return "NotSupproted" and we bypass it
5646 // if it is not impelmented. Detailed explanations can be found in
5647 // db/db_impl/db_impl.h
5648 if (!temp_s.ok()) {
5649 if (temp_s.IsNotSupported()) {
5650 temp_s.PermitUncheckedError();
5651 } else {
5652 s = temp_s;
5653 }
5654 }
5655 }
5656 }
5657
5658 if (s.ok()) {
5659 int my_disable_delete_obsolete_files;
5660
5661 {
5662 InstrumentedMutexLock l(&mutex_);
5663 versions_->options_file_number_ = options_file_number;
5664 versions_->options_file_size_ = options_file_size;
5665 my_disable_delete_obsolete_files = disable_delete_obsolete_files_;
5666 }
5667
5668 if (!my_disable_delete_obsolete_files && !is_remote_compaction_enabled) {
5669 // TODO: Should we check for errors here?
5671 }
5672 }
5673
5674 return s;
5675}
Status DeleteObsoleteOptionsFiles()
Definition db_impl.cc:5593
virtual Status RenameFile(const std::string &src, const std::string &target)=0
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RequestCompactionToken()

bool ROCKSDB_NAMESPACE::DBImpl::RequestCompactionToken ( ColumnFamilyData * cfd,
bool force,
std::unique_ptr< TaskLimiterToken > * token,
LogBuffer * log_buffer )
private

db_impl_compaction_flush.cc 파일의 64 번째 라인에서 정의되었습니다.

66 {
67 assert(*token == nullptr);
68 auto limiter = static_cast<ConcurrentTaskLimiterImpl*>(
69 cfd->ioptions()->compaction_thread_limiter.get());
70 if (limiter == nullptr) {
71 return true;
72 }
73 *token = limiter->GetToken(force);
74 if (*token != nullptr) {
75 ROCKS_LOG_BUFFER(log_buffer,
76 "Thread limiter [%s] increase [%s] compaction task, "
77 "force: %s, tasks after: %d",
78 limiter->GetName().c_str(), cfd->GetName().c_str(),
79 force ? "true" : "false", limiter->GetOutstandingTask());
80 return true;
81 }
82 return false;
83}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReserveFileNumbersBeforeIngestion()

Status ROCKSDB_NAMESPACE::DBImpl::ReserveFileNumbersBeforeIngestion ( ColumnFamilyData * cfd,
uint64_t num,
std::unique_ptr< std::list< uint64_t >::iterator > & pending_output_elem,
uint64_t * next_file_number )
private

db_impl.cc 파일의 6742 번째 라인에서 정의되었습니다.

6745 {
6746 // TODO: plumb Env::IOActivity, Env::IOPriority
6747 const ReadOptions read_options;
6748 const WriteOptions write_options;
6749
6750 Status s;
6751 SuperVersionContext dummy_sv_ctx(true /* create_superversion */);
6752 assert(nullptr != next_file_number);
6753 InstrumentedMutexLock l(&mutex_);
6755 // Do not ingest files when there is a bg_error
6756 return error_handler_.GetBGError();
6757 }
6758 pending_output_elem.reset(new std::list<uint64_t>::iterator(
6760 *next_file_number = versions_->FetchAddFileNumber(static_cast<uint64_t>(num));
6761 auto cf_options = cfd->GetLatestMutableCFOptions();
6762 VersionEdit dummy_edit;
6763 // If crash happen after a hard link established, Recover function may
6764 // reuse the file number that has already assigned to the internal file,
6765 // and this will overwrite the external file. To protect the external
6766 // file, we have to make sure the file number will never being reused.
6767 s = versions_->LogAndApply(cfd, *cf_options, read_options, write_options,
6768 &dummy_edit, &mutex_, directories_.GetDbDir());
6769 if (s.ok()) {
6770 InstallSuperVersionAndScheduleWork(cfd, &dummy_sv_ctx, *cf_options);
6771 }
6772 dummy_sv_ctx.Clean();
6773 return s;
6774}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ResetStats()

Status ROCKSDB_NAMESPACE::DBImpl::ResetStats ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 4622 번째 라인에서 정의되었습니다.

4622 {
4623 InstrumentedMutexLock l(&mutex_);
4624 for (auto* cfd : *versions_->GetColumnFamilySet()) {
4625 if (cfd->initialized()) {
4626 cfd->internal_stats()->Clear();
4627 }
4628 }
4629 return Status::OK();
4630}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RestoreAliveLogFiles()

Status ROCKSDB_NAMESPACE::DBImpl::RestoreAliveLogFiles ( const std::vector< uint64_t > & log_numbers)
private

db_impl_open.cc 파일의 1613 번째 라인에서 정의되었습니다.

1613 {
1614 if (wal_numbers.empty()) {
1615 return Status::OK();
1616 }
1617 Status s;
1618 mutex_.AssertHeld();
1620 // Mark these as alive so they'll be considered for deletion later by
1621 // FindObsoleteFiles()
1622 total_log_size_ = 0;
1623 log_empty_ = false;
1624 uint64_t min_wal_with_unflushed_data =
1625 versions_->MinLogNumberWithUnflushedData();
1626 for (auto wal_number : wal_numbers) {
1627 if (!allow_2pc() && wal_number < min_wal_with_unflushed_data) {
1628 // In non-2pc mode, the WAL files not backing unflushed data are not
1629 // alive, thus should not be added to the alive_log_files_.
1630 continue;
1631 }
1632 // We preallocate space for wals, but then after a crash and restart, those
1633 // preallocated space are not needed anymore. It is likely only the last
1634 // log has such preallocated space, so we only truncate for the last log.
1635 LogFileNumberSize log;
1637 wal_number, /*truncate=*/(wal_number == wal_numbers.back()), &log);
1638 if (!s.ok()) {
1639 break;
1640 }
1641 total_log_size_ += log.size;
1642 alive_log_files_.push_back(log);
1643 }
1644 return s;
1645}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Resume()

Status ROCKSDB_NAMESPACE::DBImpl::Resume ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 312 번째 라인에서 정의되었습니다.

312 {
314
315 InstrumentedMutexLock db_mutex(&mutex_);
316
318 // Nothing to do
319 return Status::OK();
320 }
321
323 // Don't allow a mix of manual and automatic recovery
324 return Status::Busy("Recovery in progress");
325 }
326
327 mutex_.Unlock();
328 Status s = error_handler_.RecoverFromBGError(true);
329 mutex_.Lock();
330 return s;
331}
Status RecoverFromBGError(bool is_manual=false)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ResumeImpl()

Status ROCKSDB_NAMESPACE::DBImpl::ResumeImpl ( DBRecoverContext context)
private

db_impl.cc 파일의 345 번째 라인에서 정의되었습니다.

345 {
346 mutex_.AssertHeld();
347
348 // TODO: plumb Env::IOActivity, Env::IOPriority
349 const ReadOptions read_options;
350 const WriteOptions write_options;
351
353
354 Status s;
355 if (shutdown_initiated_) {
356 // Returning shutdown status to SFM during auto recovery will cause it
357 // to abort the recovery and allow the shutdown to progress
358 s = Status::ShutdownInProgress();
359 }
360
361 if (s.ok()) {
362 Status bg_error = error_handler_.GetBGError();
363 if (bg_error.severity() > Status::Severity::kHardError) {
366 "DB resume requested but failed due to Fatal/Unrecoverable error");
367 s = bg_error;
368 }
369 }
370
371 // Make sure the IO Status stored in version set is set to OK.
372 if (s.ok()) {
373 IOStatus io_s = versions_->io_status();
374 if (io_s.IsIOError()) {
375 // If resuming from IOError resulted from MANIFEST write, then assert
376 // that we must have already set the MANIFEST writer to nullptr during
377 // clean-up phase MANIFEST writing.
378 assert(!versions_->descriptor_log_);
379 // Since we are trying to recover from MANIFEST write error, we need to
380 // switch to a new MANIFEST anyway. The old MANIFEST can be corrupted.
381 // Therefore, force writing a dummy version edit because we do not know
382 // whether there are flush jobs with non-empty data to flush, triggering
383 // appends to MANIFEST.
384 VersionEdit edit;
385 auto cfh =
386 static_cast_with_check<ColumnFamilyHandleImpl>(default_cf_handle_);
387 assert(cfh);
388 ColumnFamilyData* cfd = cfh->cfd();
389 const MutableCFOptions& cf_opts = *cfd->GetLatestMutableCFOptions();
390 s = versions_->LogAndApply(cfd, cf_opts, read_options, write_options,
391 &edit, &mutex_, directories_.GetDbDir());
392 if (!s.ok()) {
393 io_s = versions_->io_status();
394 if (!io_s.ok()) {
396 BackgroundErrorReason::kManifestWrite);
397 }
398 }
399 }
400 }
401
402 if (s.ok()) {
403 if (context.flush_reason == FlushReason::kErrorRecoveryRetryFlush) {
404 s = RetryFlushesForErrorRecovery(FlushReason::kErrorRecoveryRetryFlush,
405 true /* wait */);
406 } else {
407 // We cannot guarantee consistency of the WAL. So force flush Memtables of
408 // all the column families
409 FlushOptions flush_opts;
410 // We allow flush to stall write since we are trying to resume from error.
411 flush_opts.allow_write_stall = true;
412 s = FlushAllColumnFamilies(flush_opts, context.flush_reason);
413 }
414 if (!s.ok()) {
416 "DB resume requested but failed due to Flush failure [%s]",
417 s.ToString().c_str());
418 }
419 }
420
421 if (s.ok()) {
422 // This will notify and unblock threads waiting for error recovery to
423 // finish. Those previouly waiting threads can now proceed, which may
424 // include closing the db.
426 } else {
427 // NOTE: this is needed to pass ASSERT_STATUS_CHECKED
428 // in the DBSSTTest.DBWithMaxSpaceAllowedRandomized test.
429 // See https://github.com/facebook/rocksdb/pull/7715#issuecomment-754947952
431 }
432
433 JobContext job_context(0);
434 FindObsoleteFiles(&job_context, true);
435 mutex_.Unlock();
436 job_context.manifest_file_number = 1;
437 if (job_context.HaveSomethingToDelete()) {
438 PurgeObsoleteFiles(job_context);
439 }
440 job_context.Clean();
441
442 if (s.ok()) {
443 ROCKS_LOG_INFO(immutable_db_options_.info_log, "Successfully resumed DB");
444 } else {
445 ROCKS_LOG_INFO(immutable_db_options_.info_log, "Failed to resume DB [%s]",
446 s.ToString().c_str());
447 }
448
449 mutex_.Lock();
450 // Check for shutdown again before scheduling further compactions,
451 // since we released and re-acquired the lock above
452 if (shutdown_initiated_) {
453 s = Status::ShutdownInProgress();
454 }
455 if (s.ok() && context.flush_after_recovery) {
456 // Since we drop all non-recovery flush requests during recovery,
457 // and new memtable may fill up during recovery,
458 // schedule one more round of flush.
459 Status status = RetryFlushesForErrorRecovery(
460 FlushReason::kCatchUpAfterErrorRecovery, false /* wait */);
461 if (!status.ok()) {
462 // FlushAllColumnFamilies internally should take care of setting
463 // background error if needed.
465 "The catch up flush after successful recovery failed [%s]",
466 s.ToString().c_str());
467 }
468 // FlushAllColumnFamilies releases and re-acquires mutex.
469 if (shutdown_initiated_) {
470 s = Status::ShutdownInProgress();
471 }
472 }
473
474 if (s.ok()) {
475 for (auto cfd : *versions_->GetColumnFamilySet()) {
477 }
479 }
480
481 // Wake up any waiters - in this case, it could be the shutdown thread
483
484 // No need to check BGError again. If something happened, event listener would
485 // be notified and the operation causing it would have failed
486 return s;
487}
Status RetryFlushesForErrorRecovery(FlushReason flush_reason, bool wait)
Status FlushAllColumnFamilies(const FlushOptions &flush_options, FlushReason flush_reason)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RetryFlushesForErrorRecovery()

Status ROCKSDB_NAMESPACE::DBImpl::RetryFlushesForErrorRecovery ( FlushReason flush_reason,
bool wait )
private

db_impl_compaction_flush.cc 파일의 2569 번째 라인에서 정의되었습니다.

2570 {
2571 mutex_.AssertHeld();
2572 assert(flush_reason == FlushReason::kErrorRecoveryRetryFlush ||
2573 flush_reason == FlushReason::kCatchUpAfterErrorRecovery);
2574
2575 // Collect referenced CFDs.
2576 autovector<ColumnFamilyData*> cfds;
2577 for (ColumnFamilyData* cfd : *versions_->GetColumnFamilySet()) {
2578 if (!cfd->IsDropped() && cfd->initialized() &&
2579 cfd->imm()->NumNotFlushed() != 0) {
2580 cfd->Ref();
2581 cfd->imm()->FlushRequested();
2582 cfds.push_back(cfd);
2583 }
2584 }
2585
2586 // Submit flush requests for all immutable memtables needing flush.
2587 // `flush_memtable_ids` will be populated such that all immutable
2588 // memtables eligible for flush are waited on before this function
2589 // returns.
2590 autovector<uint64_t> flush_memtable_ids;
2592 FlushRequest flush_req;
2593 GenerateFlushRequest(cfds, flush_reason, &flush_req);
2594 EnqueuePendingFlush(flush_req);
2595 for (auto& iter : flush_req.cfd_to_max_mem_id_to_persist) {
2596 flush_memtable_ids.push_back(iter.second);
2597 }
2598 } else {
2599 for (auto cfd : cfds) {
2600 flush_memtable_ids.push_back(
2601 cfd->imm()->GetLatestMemTableID(false /* for_atomic_flush */));
2602 // Impose no bound on the highest memtable ID flushed. There is no
2603 // reason to do so outside of atomic flush.
2604 FlushRequest flush_req{
2605 flush_reason,
2606 {{cfd,
2607 std::numeric_limits<uint64_t>::max() /* max_mem_id_to_persist */}}};
2608 if (EnqueuePendingFlush(flush_req)) {
2609 cfd->SetFlushSkipReschedule();
2610 };
2611 }
2612 }
2614
2615 Status s;
2616 if (wait) {
2617 mutex_.Unlock();
2618 autovector<const uint64_t*> flush_memtable_id_ptrs;
2619 for (auto& flush_memtable_id : flush_memtable_ids) {
2620 flush_memtable_id_ptrs.push_back(&flush_memtable_id);
2621 }
2622 s = WaitForFlushMemTables(cfds, flush_memtable_id_ptrs,
2623 true /* resuming_from_bg_err */, flush_reason);
2624 mutex_.Lock();
2625 }
2626
2627 for (auto* cfd : cfds) {
2628 cfd->UnrefAndTryDelete();
2629 }
2630 return s;
2631}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReturnAndCleanupSuperVersion() [1/2]

void ROCKSDB_NAMESPACE::DBImpl::ReturnAndCleanupSuperVersion ( ColumnFamilyData * cfd,
SuperVersion * sv )

db_impl.cc 파일의 4704 번째 라인에서 정의되었습니다.

4705 {
4706 if (!cfd->ReturnThreadLocalSuperVersion(sv)) {
4708 }
4709}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ReturnAndCleanupSuperVersion() [2/2]

void ROCKSDB_NAMESPACE::DBImpl::ReturnAndCleanupSuperVersion ( uint32_t colun_family_id,
SuperVersion * sv )

db_impl.cc 파일의 4712 번째 라인에서 정의되었습니다.

4713 {
4714 auto column_family_set = versions_->GetColumnFamilySet();
4715 auto cfd = column_family_set->GetColumnFamily(column_family_id);
4716
4717 // If SuperVersion is held, and we successfully fetched a cfd using
4718 // GetAndRefSuperVersion(), it must still exist.
4719 assert(cfd != nullptr);
4721}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ RunManualCompaction()

Status ROCKSDB_NAMESPACE::DBImpl::RunManualCompaction ( ColumnFamilyData * cfd,
int input_level,
int output_level,
const CompactRangeOptions & compact_range_options,
const Slice * begin,
const Slice * end,
bool exclusive,
bool disallow_trivial_move,
uint64_t max_file_num_to_ignore,
const std::string & trim_ts,
int * final_output_level = nullptr )

db_impl_compaction_flush.cc 파일의 2023 번째 라인에서 정의되었습니다.

2028 {
2029 assert(input_level == ColumnFamilyData::kCompactAllLevels ||
2030 input_level >= 0);
2031
2032 InternalKey begin_storage, end_storage;
2033 CompactionArg* ca = nullptr;
2034
2035 bool scheduled = false;
2036 bool unscheduled = false;
2037 Env::Priority thread_pool_priority = Env::Priority::TOTAL;
2038 bool manual_conflict = false;
2039
2040 ManualCompactionState manual(
2041 cfd, input_level, output_level, compact_range_options.target_path_id,
2042 exclusive, disallow_trivial_move, compact_range_options.canceled);
2043 // For universal compaction, we enforce every manual compaction to compact
2044 // all files.
2045 if (begin == nullptr ||
2046 cfd->ioptions()->compaction_style == kCompactionStyleUniversal ||
2047 cfd->ioptions()->compaction_style == kCompactionStyleFIFO) {
2048 manual.begin = nullptr;
2049 } else {
2050 begin_storage.SetMinPossibleForUserKey(*begin);
2051 manual.begin = &begin_storage;
2052 }
2053 if (end == nullptr ||
2054 cfd->ioptions()->compaction_style == kCompactionStyleUniversal ||
2055 cfd->ioptions()->compaction_style == kCompactionStyleFIFO) {
2056 manual.end = nullptr;
2057 } else {
2058 end_storage.SetMaxPossibleForUserKey(*end);
2059 manual.end = &end_storage;
2060 }
2061
2062 TEST_SYNC_POINT("DBImpl::RunManualCompaction:0");
2063 TEST_SYNC_POINT("DBImpl::RunManualCompaction:1");
2064 InstrumentedMutexLock l(&mutex_);
2065
2066 if (manual_compaction_paused_ > 0) {
2067 // Does not make sense to `AddManualCompaction()` in this scenario since
2068 // `DisableManualCompaction()` just waited for the manual compaction queue
2069 // to drain. So return immediately.
2070 TEST_SYNC_POINT("DBImpl::RunManualCompaction:PausedAtStart");
2071 manual.status =
2072 Status::Incomplete(Status::SubCode::kManualCompactionPaused);
2073 manual.done = true;
2074 return manual.status;
2075 }
2076
2077 // When a manual compaction arrives, temporarily disable scheduling of
2078 // non-manual compactions and wait until the number of scheduled compaction
2079 // jobs drops to zero. This used to be needed to ensure that this manual
2080 // compaction can compact any range of keys/files. Now it is optional
2081 // (see `CompactRangeOptions::exclusive_manual_compaction`). The use case for
2082 // `exclusive_manual_compaction=true` is unclear beyond not trusting the code.
2083 //
2084 // HasPendingManualCompaction() is true when at least one thread is inside
2085 // RunManualCompaction(), i.e. during that time no other compaction will
2086 // get scheduled (see MaybeScheduleFlushOrCompaction).
2087 //
2088 // Note that the following loop doesn't stop more that one thread calling
2089 // RunManualCompaction() from getting to the second while loop below.
2090 // However, only one of them will actually schedule compaction, while
2091 // others will wait on a condition variable until it completes.
2092
2093 AddManualCompaction(&manual);
2094 TEST_SYNC_POINT_CALLBACK("DBImpl::RunManualCompaction:NotScheduled", &mutex_);
2095 if (exclusive) {
2096 // Limitation: there's no way to wake up the below loop when user sets
2097 // `*manual.canceled`. So `CompactRangeOptions::exclusive_manual_compaction`
2098 // and `CompactRangeOptions::canceled` might not work well together.
2099 while (bg_bottom_compaction_scheduled_ > 0 ||
2100 bg_compaction_scheduled_ > 0) {
2101 if (manual_compaction_paused_ > 0 || manual.canceled == true) {
2102 // Pretend the error came from compaction so the below cleanup/error
2103 // handling code can process it.
2104 manual.done = true;
2105 manual.status =
2106 Status::Incomplete(Status::SubCode::kManualCompactionPaused);
2107 break;
2108 }
2109 TEST_SYNC_POINT("DBImpl::RunManualCompaction:WaitScheduled");
2112 "[%s] Manual compaction waiting for all other scheduled background "
2113 "compactions to finish",
2114 cfd->GetName().c_str());
2115 bg_cv_.Wait();
2116 }
2117 }
2118
2119 LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL,
2121
2122 ROCKS_LOG_BUFFER(&log_buffer, "[%s] Manual compaction starting",
2123 cfd->GetName().c_str());
2124
2125 // We don't check bg_error_ here, because if we get the error in compaction,
2126 // the compaction will set manual.status to bg_error_ and set manual.done to
2127 // true.
2128 while (!manual.done) {
2130 manual_conflict = false;
2131 Compaction* compaction = nullptr;
2132 if (ShouldntRunManualCompaction(&manual) || (manual.in_progress == true) ||
2133 scheduled ||
2134 (((manual.manual_end = &manual.tmp_storage1) != nullptr) &&
2135 ((compaction = manual.cfd->CompactRange(
2136 *manual.cfd->GetLatestMutableCFOptions(), mutable_db_options_,
2137 manual.input_level, manual.output_level, compact_range_options,
2138 manual.begin, manual.end, &manual.manual_end, &manual_conflict,
2139 max_file_num_to_ignore, trim_ts)) == nullptr &&
2140 manual_conflict))) {
2141 if (!manual.done) {
2142 bg_cv_.Wait();
2143 }
2144 if (manual_compaction_paused_ > 0 && scheduled && !unscheduled) {
2145 assert(thread_pool_priority != Env::Priority::TOTAL);
2146 // unschedule all manual compactions
2147 auto unscheduled_task_num = env_->UnSchedule(
2148 GetTaskTag(TaskType::kManualCompaction), thread_pool_priority);
2149 if (unscheduled_task_num > 0) {
2152 "[%s] Unscheduled %d number of manual compactions from the "
2153 "thread-pool",
2154 cfd->GetName().c_str(), unscheduled_task_num);
2155 // it may unschedule other manual compactions, notify others.
2156 bg_cv_.SignalAll();
2157 }
2158 unscheduled = true;
2159 TEST_SYNC_POINT("DBImpl::RunManualCompaction:Unscheduled");
2160 }
2161 if (scheduled && manual.incomplete == true) {
2162 assert(!manual.in_progress);
2163 scheduled = false;
2164 manual.incomplete = false;
2165 }
2166 } else if (!scheduled) {
2167 if (compaction == nullptr) {
2168 manual.done = true;
2169 if (final_output_level) {
2170 // No compaction needed or there is a conflicting compaction.
2171 // Still set `final_output_level` to the level where we would
2172 // have compacted to.
2173 *final_output_level = output_level;
2174 if (output_level == ColumnFamilyData::kCompactToBaseLevel) {
2175 *final_output_level = cfd->current()->storage_info()->base_level();
2176 }
2177 }
2178 bg_cv_.SignalAll();
2179 continue;
2180 }
2181 ca = new CompactionArg;
2182 ca->db = this;
2183 ca->prepicked_compaction = new PrepickedCompaction;
2184 ca->prepicked_compaction->manual_compaction_state = &manual;
2185 ca->prepicked_compaction->compaction = compaction;
2187 cfd, true, &ca->prepicked_compaction->task_token, &log_buffer)) {
2188 // Don't throttle manual compaction, only count outstanding tasks.
2189 assert(false);
2190 }
2191 manual.incomplete = false;
2192 if (compaction->bottommost_level() &&
2193 env_->GetBackgroundThreads(Env::Priority::BOTTOM) > 0) {
2195 ca->compaction_pri_ = Env::Priority::BOTTOM;
2196 env_->Schedule(&DBImpl::BGWorkBottomCompaction, ca,
2197 Env::Priority::BOTTOM,
2198 GetTaskTag(TaskType::kManualCompaction),
2199 &DBImpl::UnscheduleCompactionCallback);
2200 thread_pool_priority = Env::Priority::BOTTOM;
2201 } else {
2203 ca->compaction_pri_ = Env::Priority::LOW;
2204 env_->Schedule(&DBImpl::BGWorkCompaction, ca, Env::Priority::LOW,
2205 GetTaskTag(TaskType::kManualCompaction),
2206 &DBImpl::UnscheduleCompactionCallback);
2207 thread_pool_priority = Env::Priority::LOW;
2208 }
2209 scheduled = true;
2210 TEST_SYNC_POINT("DBImpl::RunManualCompaction:Scheduled");
2211 if (final_output_level) {
2212 *final_output_level = compaction->output_level();
2213 }
2214 }
2215 if (!scheduled) {
2216 // There is nothing scheduled to wait on, so any cancellation can end the
2217 // manual now.
2218 if (manual_compaction_paused_ > 0 || manual.canceled == true) {
2219 // Stop waiting since it was canceled. Pretend the error came from
2220 // compaction so the below cleanup/error handling code can process it.
2221 manual.done = true;
2222 manual.status =
2223 Status::Incomplete(Status::SubCode::kManualCompactionPaused);
2224 }
2225 }
2226 }
2227
2228 log_buffer.FlushBufferToLog();
2229 assert(!manual.in_progress);
2231 RemoveManualCompaction(&manual);
2232 // if the manual job is unscheduled, try schedule other jobs in case there's
2233 // any unscheduled compaction job which was blocked by exclusive manual
2234 // compaction.
2235 if (manual.status.IsIncomplete() &&
2236 manual.status.subcode() == Status::SubCode::kManualCompactionPaused) {
2238 }
2239 bg_cv_.SignalAll();
2240 return manual.status;
2241}
bool ShouldntRunManualCompaction(ManualCompactionState *m)
void AddManualCompaction(ManualCompactionState *m)
void RemoveManualCompaction(ManualCompactionState *m)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ScheduleBgLogWriterClose()

void ROCKSDB_NAMESPACE::DBImpl::ScheduleBgLogWriterClose ( JobContext * job_context)

db_impl.cc 파일의 1253 번째 라인에서 정의되었습니다.

1253 {
1254 mutex_.AssertHeld();
1255 if (!job_context->logs_to_free.empty()) {
1256 for (auto l : job_context->logs_to_free) {
1258 }
1259 job_context->logs_to_free.clear();
1260 }
1261}
void AddToLogsToFreeQueue(log::Writer *log_writer)
Definition db_impl.h:1055
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ScheduleFlushes()

Status ROCKSDB_NAMESPACE::DBImpl::ScheduleFlushes ( WriteContext * context)
private

db_impl_write.cc 파일의 2315 번째 라인에서 정의되었습니다.

2315 {
2316 autovector<ColumnFamilyData*> cfds;
2319 for (auto cfd : cfds) {
2320 cfd->Ref();
2321 }
2323 } else {
2324 ColumnFamilyData* tmp_cfd;
2325 while ((tmp_cfd = flush_scheduler_.TakeNextColumnFamily()) != nullptr) {
2326 cfds.push_back(tmp_cfd);
2327 }
2328 MaybeFlushStatsCF(&cfds);
2329 }
2330 Status status;
2331 WriteThread::Writer nonmem_w;
2332 if (two_write_queues_) {
2333 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
2334 }
2335
2336 TEST_SYNC_POINT_CALLBACK("DBImpl::ScheduleFlushes:PreSwitchMemtable",
2337 nullptr);
2338 for (auto& cfd : cfds) {
2339 if (status.ok() && !cfd->mem()->IsEmpty()) {
2340 status = SwitchMemtable(cfd, context);
2341 }
2342 if (cfd->UnrefAndTryDelete()) {
2343 cfd = nullptr;
2344 }
2345 }
2346
2347 if (two_write_queues_) {
2349 }
2350
2351 if (status.ok()) {
2354 FlushRequest flush_req;
2355 GenerateFlushRequest(cfds, FlushReason::kWriteBufferFull, &flush_req);
2356 EnqueuePendingFlush(flush_req);
2357 } else {
2358 for (auto* cfd : cfds) {
2359 FlushRequest flush_req;
2360 GenerateFlushRequest({cfd}, FlushReason::kWriteBufferFull, &flush_req);
2361 EnqueuePendingFlush(flush_req);
2362 }
2363 }
2365 }
2366 return status;
2367}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SchedulePendingPurge()

void ROCKSDB_NAMESPACE::DBImpl::SchedulePendingPurge ( std::string fname,
std::string dir_to_sync,
FileType type,
uint64_t number,
int job_id )
private

db_impl_compaction_flush.cc 파일의 3073 번째 라인에서 정의되었습니다.

3074 {
3075 mutex_.AssertHeld();
3076 if (reject_new_background_jobs_) {
3077 return;
3078 }
3079 PurgeFileInfo file_info(fname, dir_to_sync, type, number, job_id);
3080 purge_files_.insert({{number, std::move(file_info)}});
3081}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SchedulePurge()

void ROCKSDB_NAMESPACE::DBImpl::SchedulePurge ( )

db_impl.cc 파일의 1954 번째 라인에서 정의되었습니다.

1954 {
1955 mutex_.AssertHeld();
1956 assert(opened_successfully_);
1957
1958 // Purge operations are put into High priority queue
1960 env_->Schedule(&DBImpl::BGWorkPurge, this, Env::Priority::HIGH, nullptr);
1961}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SelectColumnFamiliesForAtomicFlush()

void ROCKSDB_NAMESPACE::DBImpl::SelectColumnFamiliesForAtomicFlush ( autovector< ColumnFamilyData * > * selected_cfds,
const autovector< ColumnFamilyData * > & provided_candidate_cfds = {},
FlushReason flush_reason = FlushReason::kOthers )
private

db_impl_write.cc 파일의 1843 번째 라인에서 정의되었습니다.

1846 {
1847 mutex_.AssertHeld();
1848 assert(selected_cfds);
1849
1850 autovector<ColumnFamilyData*> candidate_cfds;
1851
1852 // Generate candidate cfds if not provided
1853 if (provided_candidate_cfds.empty()) {
1854 for (ColumnFamilyData* cfd : *versions_->GetColumnFamilySet()) {
1855 if (!cfd->IsDropped() && cfd->initialized()) {
1856 cfd->Ref();
1857 candidate_cfds.push_back(cfd);
1858 }
1859 }
1860 } else {
1861 candidate_cfds = provided_candidate_cfds;
1862 }
1863
1864 for (ColumnFamilyData* cfd : candidate_cfds) {
1865 if (cfd->IsDropped()) {
1866 continue;
1867 }
1868 if (cfd->imm()->NumNotFlushed() != 0 || !cfd->mem()->IsEmpty() ||
1870 IsRecoveryFlush(flush_reason)) {
1871 selected_cfds->push_back(cfd);
1872 }
1873 }
1874
1875 // Unref the newly generated candidate cfds (when not provided) in
1876 // `candidate_cfds`
1877 if (provided_candidate_cfds.empty()) {
1878 for (auto candidate_cfd : candidate_cfds) {
1879 candidate_cfd->UnrefAndTryDelete();
1880 }
1881 }
1882}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ seq_per_batch()

bool ROCKSDB_NAMESPACE::DBImpl::seq_per_batch ( ) const
inline

db_impl.h 파일의 1337 번째 라인에서 정의되었습니다.

1337{ return seq_per_batch_; }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetDBId()

void ROCKSDB_NAMESPACE::DBImpl::SetDBId ( std::string && id,
bool read_only,
VersionEdit * version_edit )
protected

db_impl_files.cc 파일의 972 번째 라인에서 정의되었습니다.

973 {
974 assert(db_id_.empty());
975 assert(!id.empty());
976 db_id_ = std::move(id);
977 if (!read_only && version_edit) {
978 assert(version_edit != nullptr);
979 assert(versions_->GetColumnFamilySet() != nullptr);
980 version_edit->SetDBId(db_id_);
981 versions_->db_id_ = db_id_;
982 }
983}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetDBOptions()

Status ROCKSDB_NAMESPACE::DBImpl::SetDBOptions ( const std::unordered_map< std::string, std::string > & options_map)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 1345 번째 라인에서 정의되었습니다.

1346 {
1347 if (options_map.empty()) {
1349 "SetDBOptions(), empty input.");
1350 return Status::InvalidArgument("empty input");
1351 }
1352
1353 InstrumentedMutexLock ol(&options_mutex_);
1354 MutableDBOptions new_options;
1355 Status s;
1356 Status persist_options_status = Status::OK();
1357 bool wal_size_option_changed = false;
1358 bool wal_other_option_changed = false;
1359 WriteContext write_context;
1360 {
1361 InstrumentedMutexLock l(&mutex_);
1362 s = GetMutableDBOptionsFromStrings(mutable_db_options_, options_map,
1363 &new_options);
1364
1365 if (new_options.bytes_per_sync == 0) {
1366 new_options.bytes_per_sync = 1024 * 1024;
1367 }
1368
1369 if (MutableDBOptionsAreEqual(mutable_db_options_, new_options)) {
1371 "SetDBOptions(), input option value is not changed, "
1372 "skipping updating.");
1373 persist_options_status.PermitUncheckedError();
1374 return s;
1375 }
1376
1377 DBOptions new_db_options =
1378 BuildDBOptions(immutable_db_options_, new_options);
1379 if (s.ok()) {
1380 s = ValidateOptions(new_db_options);
1381 }
1382 if (s.ok()) {
1383 for (auto c : *versions_->GetColumnFamilySet()) {
1384 if (!c->IsDropped()) {
1385 auto cf_options = c->GetLatestCFOptions();
1386 s = ColumnFamilyData::ValidateOptions(new_db_options, cf_options);
1387 if (!s.ok()) {
1388 break;
1389 }
1390 }
1391 }
1392 }
1393 if (s.ok()) {
1394 const BGJobLimits current_bg_job_limits =
1398 /* parallelize_compactions */ true);
1399 const BGJobLimits new_bg_job_limits = GetBGJobLimits(
1400 new_options.max_background_flushes,
1401 new_options.max_background_compactions,
1402 new_options.max_background_jobs, /* parallelize_compactions */ true);
1403
1404 const bool max_flushes_increased =
1405 new_bg_job_limits.max_flushes > current_bg_job_limits.max_flushes;
1406 const bool max_compactions_increased =
1407 new_bg_job_limits.max_compactions >
1408 current_bg_job_limits.max_compactions;
1409 const bool offpeak_time_changed =
1410 versions_->offpeak_time_option().daily_offpeak_time_utc !=
1411 new_db_options.daily_offpeak_time_utc;
1412
1413 if (max_flushes_increased || max_compactions_increased ||
1414 offpeak_time_changed) {
1415 if (max_flushes_increased) {
1416 env_->IncBackgroundThreadsIfNeeded(new_bg_job_limits.max_flushes,
1417 Env::Priority::HIGH);
1418 }
1419 if (max_compactions_increased) {
1420 env_->IncBackgroundThreadsIfNeeded(new_bg_job_limits.max_compactions,
1421 Env::Priority::LOW);
1422 }
1423 if (offpeak_time_changed) {
1424 versions_->ChangeOffpeakTimeOption(
1425 new_db_options.daily_offpeak_time_utc);
1426 }
1427
1429 }
1430
1431 mutex_.Unlock();
1432 if (new_options.stats_dump_period_sec == 0) {
1433 s = periodic_task_scheduler_.Unregister(PeriodicTaskType::kDumpStats);
1434 } else {
1436 PeriodicTaskType::kDumpStats,
1437 periodic_task_functions_.at(PeriodicTaskType::kDumpStats),
1438 new_options.stats_dump_period_sec);
1439 }
1440 if (new_options.max_total_wal_size !=
1442 max_total_wal_size_.store(new_options.max_total_wal_size,
1443 std::memory_order_release);
1444 }
1445 if (s.ok()) {
1446 if (new_options.stats_persist_period_sec == 0) {
1448 PeriodicTaskType::kPersistStats);
1449 } else {
1451 PeriodicTaskType::kPersistStats,
1452 periodic_task_functions_.at(PeriodicTaskType::kPersistStats),
1453 new_options.stats_persist_period_sec);
1454 }
1455 }
1456 mutex_.Lock();
1457 if (!s.ok()) {
1458 return s;
1459 }
1460
1462 new_options.delayed_write_rate);
1463 table_cache_.get()->SetCapacity(new_options.max_open_files == -1
1464 ? TableCache::kInfiniteCapacity
1465 : new_options.max_open_files - 10);
1466 wal_other_option_changed = mutable_db_options_.wal_bytes_per_sync !=
1467 new_options.wal_bytes_per_sync;
1468 wal_size_option_changed = mutable_db_options_.max_total_wal_size !=
1469 new_options.max_total_wal_size;
1470 mutable_db_options_ = new_options;
1471 file_options_for_compaction_ = FileOptions(new_db_options);
1472 file_options_for_compaction_ = fs_->OptimizeForCompactionTableWrite(
1473 file_options_for_compaction_, immutable_db_options_);
1474 versions_->ChangeFileOptions(mutable_db_options_);
1475 // TODO(xiez): clarify why apply optimize for read to write options
1476 file_options_for_compaction_ = fs_->OptimizeForCompactionTableRead(
1477 file_options_for_compaction_, immutable_db_options_);
1478 if (wal_other_option_changed || wal_size_option_changed) {
1479 WriteThread::Writer w;
1480 write_thread_.EnterUnbatched(&w, &mutex_);
1481 if (wal_other_option_changed ||
1482 total_log_size_ > GetMaxTotalWalSize()) {
1483 Status purge_wal_status = SwitchWAL(&write_context);
1484 if (!purge_wal_status.ok()) {
1486 "Unable to purge WAL files in SetDBOptions() -- %s",
1487 purge_wal_status.ToString().c_str());
1488 }
1489 }
1491 }
1492 persist_options_status =
1493 WriteOptionsFile(WriteOptions(), true /*db_mutex_already_held*/);
1494 } else {
1495 // To get here, we must have had invalid options and will not attempt to
1496 // persist the options, which means the status is "OK/Uninitialized.
1497 persist_options_status.PermitUncheckedError();
1498 }
1499 }
1500 ROCKS_LOG_INFO(immutable_db_options_.info_log, "SetDBOptions(), inputs:");
1501 for (const auto& o : options_map) {
1502 ROCKS_LOG_INFO(immutable_db_options_.info_log, "%s: %s\n", o.first.c_str(),
1503 o.second.c_str());
1504 }
1505 if (s.ok()) {
1506 ROCKS_LOG_INFO(immutable_db_options_.info_log, "SetDBOptions() succeeded");
1507 new_options.Dump(immutable_db_options_.info_log.get());
1508 if (!persist_options_status.ok()) {
1510 s = Status::IOError(
1511 "SetDBOptions() succeeded, but unable to persist options",
1512 persist_options_status.ToString());
1513 }
1515 "Unable to persist options in SetDBOptions() -- %s",
1516 persist_options_status.ToString().c_str());
1517 }
1518 } else {
1519 ROCKS_LOG_WARN(immutable_db_options_.info_log, "SetDBOptions failed");
1520 }
1522 return s;
1523}
virtual void IncBackgroundThreadsIfNeeded(int number, Priority pri)=0
void set_max_delayed_write_rate(uint64_t write_rate)
bool MutableDBOptionsAreEqual(const MutableDBOptions &this_options, const MutableDBOptions &that_options)
Status GetMutableDBOptionsFromStrings(const MutableDBOptions &base_options, const std::unordered_map< std::string, std::string > &options_map, MutableDBOptions *new_options)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetDbSessionId()

void ROCKSDB_NAMESPACE::DBImpl::SetDbSessionId ( )
protected

db_impl.cc 파일의 5276 번째 라인에서 정의되었습니다.

5276 {
5278 TEST_SYNC_POINT_CALLBACK("DBImpl::SetDbSessionId", &db_session_id_);
5279}
static std::string GenerateDbSessionId(Env *env)
Definition db_impl.cc:5261
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetLastPublishedSequence()

void ROCKSDB_NAMESPACE::DBImpl::SetLastPublishedSequence ( SequenceNumber seq)
virtual

db_impl.cc 파일의 1905 번째 라인에서 정의되었습니다.

1905 {
1906 versions_->SetLastPublishedSequence(seq);
1907}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetOptions() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::SetOptions ( ColumnFamilyHandle * column_family,
const std::unordered_map< std::string, std::string > & options_map )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 1272 번째 라인에서 정의되었습니다.

1274 {
1275 // TODO: plumb Env::IOActivity, Env::IOPriority
1276 const ReadOptions read_options;
1277 const WriteOptions write_options;
1278
1279 auto* cfd =
1280 static_cast_with_check<ColumnFamilyHandleImpl>(column_family)->cfd();
1281 if (options_map.empty()) {
1283 "SetOptions() on column family [%s], empty input",
1284 cfd->GetName().c_str());
1285 return Status::InvalidArgument("empty input");
1286 }
1287
1288 InstrumentedMutexLock ol(&options_mutex_);
1289 MutableCFOptions new_options;
1290 Status s;
1291 Status persist_options_status;
1292 SuperVersionContext sv_context(/* create_superversion */ true);
1293 {
1294 auto db_options = GetDBOptions();
1295 InstrumentedMutexLock l(&mutex_);
1296 s = cfd->SetOptions(db_options, options_map);
1297 if (s.ok()) {
1298 new_options = *cfd->GetLatestMutableCFOptions();
1299 // Append new version to recompute compaction score.
1300 VersionEdit dummy_edit;
1301 s = versions_->LogAndApply(cfd, new_options, read_options, write_options,
1302 &dummy_edit, &mutex_, directories_.GetDbDir());
1303 // Trigger possible flush/compactions. This has to be before we persist
1304 // options to file, otherwise there will be a deadlock with writer
1305 // thread.
1306 InstallSuperVersionAndScheduleWork(cfd, &sv_context, new_options);
1307
1308 persist_options_status =
1309 WriteOptionsFile(write_options, true /*db_mutex_already_held*/);
1310 bg_cv_.SignalAll();
1311 }
1312 }
1313 sv_context.Clean();
1314
1315 if (s.ok() && (options_map.count("preserve_internal_time_seconds") > 0 ||
1316 options_map.count("preclude_last_level_data_seconds") > 0)) {
1317 s = RegisterRecordSeqnoTimeWorker(read_options, write_options,
1318 false /* is_new_db*/);
1319 }
1320
1323 "SetOptions() on column family [%s], inputs:", cfd->GetName().c_str());
1324 for (const auto& o : options_map) {
1325 ROCKS_LOG_INFO(immutable_db_options_.info_log, "%s: %s\n", o.first.c_str(),
1326 o.second.c_str());
1327 }
1328 if (s.ok()) {
1330 "[%s] SetOptions() succeeded", cfd->GetName().c_str());
1331 new_options.Dump(immutable_db_options_.info_log.get());
1332 if (!persist_options_status.ok()) {
1333 // NOTE: WriteOptionsFile already logs on failure
1334 s = persist_options_status;
1335 }
1336 } else {
1337 persist_options_status.PermitUncheckedError(); // less important
1338 ROCKS_LOG_WARN(immutable_db_options_.info_log, "[%s] SetOptions() failed",
1339 cfd->GetName().c_str());
1340 }
1342 return s;
1343}
DBOptions GetDBOptions() const override
Definition db_impl.cc:4502
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetOptions() [2/2]

virtual Status ROCKSDB_NAMESPACE::DB::SetOptions ( const std::unordered_map< std::string, std::string > & new_options)
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 1525 번째 라인에서 정의되었습니다.

1526 {
1527 return SetOptions(DefaultColumnFamily(), new_options);
1528 }

◆ SetRecoverableStatePreReleaseCallback()

void ROCKSDB_NAMESPACE::DBImpl::SetRecoverableStatePreReleaseCallback ( PreReleaseCallback * callback)

db_impl_write.cc 파일의 146 번째 라인에서 정의되었습니다.

147 {
149}
std::unique_ptr< PreReleaseCallback > recoverable_state_pre_release_callback_
Definition db_impl.h:2955
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetSnapshotChecker()

void ROCKSDB_NAMESPACE::DBImpl::SetSnapshotChecker ( SnapshotChecker * snapshot_checker)

db_impl_compaction_flush.cc 파일의 4353 번째 라인에서 정의되었습니다.

4353 {
4354 InstrumentedMutexLock l(&mutex_);
4355 // snapshot_checker_ should only set once. If we need to set it multiple
4356 // times, we need to make sure the old one is not deleted while it is still
4357 // using by a compaction job.
4358 assert(!snapshot_checker_);
4359 snapshot_checker_.reset(snapshot_checker);
4360}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetupDBId()

Status ROCKSDB_NAMESPACE::DBImpl::SetupDBId ( const WriteOptions & write_options,
bool read_only,
bool is_new_db,
bool is_retry,
VersionEdit * version_edit )
protected

db_impl_files.cc 파일의 985 번째 라인에서 정의되었습니다.

987 {
988 Status s;
989 if (!is_new_db) {
990 // Check for the IDENTITY file and create it if not there or
991 // broken or not matching manifest
992 std::string db_id_in_file;
993 s = fs_->FileExists(IdentityFileName(dbname_), IOOptions(), nullptr);
994 if (s.ok()) {
995 IOOptions opts;
996 if (is_retry) {
997 opts.verify_and_reconstruct_read = true;
998 }
999 s = GetDbIdentityFromIdentityFile(opts, &db_id_in_file);
1000 if (s.ok() && !db_id_in_file.empty()) {
1001 if (db_id_.empty()) {
1002 // Loaded from file and wasn't already known from manifest
1003 SetDBId(std::move(db_id_in_file), read_only, version_edit);
1004 return s;
1005 } else if (db_id_ == db_id_in_file) {
1006 // Loaded from file and matches manifest
1007 return s;
1008 }
1009 }
1010 }
1011 if (s.IsNotFound()) {
1012 s = Status::OK();
1013 }
1014 if (!s.ok()) {
1015 assert(s.IsIOError());
1016 return s;
1017 }
1018 }
1019 // Otherwise IDENTITY file is missing or no good.
1020 // Generate new id if needed
1021 if (db_id_.empty()) {
1022 SetDBId(env_->GenerateUniqueId(), read_only, version_edit);
1023 }
1024 // Persist it to IDENTITY file if allowed
1025 if (!read_only && immutable_db_options_.write_identity_file) {
1026 s = SetIdentityFile(write_options, env_, dbname_,
1028 db_id_);
1029 }
1030 // NOTE: an obsolete IDENTITY file with write_identity_file=false is handled
1031 // elsewhere, so that it's only deleted after successful recovery
1032 return s;
1033}
void SetDBId(std::string &&id, bool read_only, VersionEdit *version_edit)
virtual Status GetDbIdentityFromIdentityFile(const IOOptions &opts, std::string *identity) const
Definition db_impl.cc:5229
virtual std::string GenerateUniqueId()
Definition env.cc:786
Status SetIdentityFile(const WriteOptions &write_options, Env *env, const std::string &dbname, Temperature temp, const std::string &db_id)
Definition filename.cc:429
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ShouldntRunManualCompaction()

bool ROCKSDB_NAMESPACE::DBImpl::ShouldntRunManualCompaction ( ManualCompactionState * m)
private

db_impl_compaction_flush.cc 파일의 4119 번째 라인에서 정의되었습니다.

4119 {
4120 if (m->exclusive) {
4121 return (bg_bottom_compaction_scheduled_ > 0 ||
4122 bg_compaction_scheduled_ > 0);
4123 }
4124 std::deque<ManualCompactionState*>::iterator it =
4126 bool seen = false;
4127 while (it != manual_compaction_dequeue_.end()) {
4128 if (m == (*it)) {
4129 ++it;
4130 seen = true;
4131 continue;
4132 } else if (MCOverlap(m, (*it)) && (!seen && !(*it)->in_progress)) {
4133 // Consider the other manual compaction *it, conflicts if:
4134 // overlaps with m
4135 // and (*it) is ahead in the queue and is not yet in progress
4136 return true;
4137 }
4138 ++it;
4139 }
4140 return false;
4141}
bool MCOverlap(ManualCompactionState *m, ManualCompactionState *m1)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ShouldPurge()

bool ROCKSDB_NAMESPACE::DBImpl::ShouldPurge ( uint64_t file_number) const
private

db_impl_compaction_flush.cc 파일의 4341 번째 라인에서 정의되었습니다.

4341 {
4342 return files_grabbed_for_purge_.find(file_number) ==
4344 purge_files_.find(file_number) == purge_files_.end();
4345}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ShouldReferenceSuperVersion()

bool ROCKSDB_NAMESPACE::DBImpl::ShouldReferenceSuperVersion ( const MergeContext & merge_context)
private

db_impl.cc 파일의 2298 번째 라인에서 정의되었습니다.

2298 {
2299 // If both thresholds are reached, a function returning merge operands as
2300 // `PinnableSlice`s should reference the `SuperVersion` to avoid large and/or
2301 // numerous `memcpy()`s.
2302 //
2303 // The below constants enable the optimization conservatively. They are
2304 // verified to not regress `GetMergeOperands()` latency in the following
2305 // scenarios.
2306 //
2307 // - CPU: two socket Intel(R) Xeon(R) Gold 6138 CPU @ 2.00GHz
2308 // - `GetMergeOperands()` threads: 1 - 32
2309 // - Entry size: 32 bytes - 4KB
2310 // - Merges per key: 1 - 16K
2311 // - LSM component: memtable
2312 //
2313 // TODO(ajkr): expand measurement to SST files.
2314 static const size_t kNumBytesForSvRef = 32768;
2315 static const size_t kLog2AvgBytesForSvRef = 8; // 256 bytes
2316
2317 size_t num_bytes = 0;
2318 for (const Slice& sl : merge_context.GetOperands()) {
2319 num_bytes += sl.size();
2320 }
2321 return num_bytes >= kNumBytesForSvRef &&
2322 (num_bytes >> kLog2AvgBytesForSvRef) >=
2323 merge_context.GetOperands().size();
2324}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ShouldRescheduleFlushRequestToRetainUDT()

bool ROCKSDB_NAMESPACE::DBImpl::ShouldRescheduleFlushRequestToRetainUDT ( const FlushRequest & flush_req)
private

db_impl_compaction_flush.cc 파일의 85 번째 라인에서 정의되었습니다.

86 {
87 mutex_.AssertHeld();
88 assert(flush_req.cfd_to_max_mem_id_to_persist.size() == 1);
89 ColumnFamilyData* cfd = flush_req.cfd_to_max_mem_id_to_persist.begin()->first;
90 if (cfd->GetAndClearFlushSkipReschedule()) {
91 return false;
92 }
93 uint64_t max_memtable_id =
94 flush_req.cfd_to_max_mem_id_to_persist.begin()->second;
95 if (cfd->IsDropped() ||
96 !cfd->ShouldPostponeFlushToRetainUDT(max_memtable_id)) {
97 return false;
98 }
99 // Check if holding on the flush will cause entering write stall mode.
100 // Write stall entered because of the accumulation of write buffers can be
101 // alleviated if we continue with the flush instead of postponing it.
102 const auto& mutable_cf_options = *cfd->GetLatestMutableCFOptions();
103
104 // Use the same criteria as WaitUntilFlushWouldNotStallWrites does w.r.t
105 // defining what a write stall is about to happen means. If this uses a
106 // stricter criteria, for example, a write stall is about to happen if the
107 // last memtable is 10% full, there is a possibility that manual flush could
108 // be waiting in `WaitUntilFlushWouldNotStallWrites` with the incorrect
109 // expectation that others will clear up the excessive memtables and
110 // eventually let it proceed. The others in this case won't start clearing
111 // until the last memtable is 10% full. To avoid that scenario, the criteria
112 // this uses should be the same or less strict than
113 // `WaitUntilFlushWouldNotStallWrites` does.
114 WriteStallCondition write_stall =
115 ColumnFamilyData::GetWriteStallConditionAndCause(
116 cfd->GetUnflushedMemTableCountForWriteStallCheck(),
117 /*num_l0_files=*/0,
118 /*num_compaction_needed_bytes=*/0, mutable_cf_options,
119 *cfd->ioptions())
120 .first;
121 if (write_stall != WriteStallCondition::kNormal) {
122 return false;
123 }
124 return true;
125}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SingleDelete() [1/4]

Status ROCKSDB_NAMESPACE::DBImpl::SingleDelete ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 105 번째 라인에서 정의되었습니다.

107 {
108 const Status s = FailIfCfHasTs(column_family);
109 if (!s.ok()) {
110 return s;
111 }
112 return DB::SingleDelete(write_options, column_family, key);
113}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SingleDelete() [2/4]

Status ROCKSDB_NAMESPACE::DBImpl::SingleDelete ( const WriteOptions & options,
ColumnFamilyHandle * column_family,
const Slice & key,
const Slice & ts )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 115 번째 라인에서 정의되었습니다.

117 {
118 const Status s = FailIfTsMismatchCf(column_family, ts);
119 if (!s.ok()) {
120 return s;
121 }
122 return DB::SingleDelete(write_options, column_family, key, ts);
123}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ SingleDelete() [3/4]

virtual Status ROCKSDB_NAMESPACE::DB::SingleDelete ( const WriteOptions & options,
const Slice & key )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 524 번째 라인에서 정의되었습니다.

524 {
525 return SingleDelete(options, DefaultColumnFamily(), key);
526 }
Status SingleDelete(const WriteOptions &options, ColumnFamilyHandle *column_family, const Slice &key) override

◆ SingleDelete() [4/4]

virtual Status ROCKSDB_NAMESPACE::DB::SingleDelete ( const WriteOptions & options,
const Slice & key,
const Slice & ts )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db.h 파일의 527 번째 라인에서 정의되었습니다.

528 {
529 return SingleDelete(options, DefaultColumnFamily(), key, ts);
530 }

◆ snapshots()

const SnapshotList & ROCKSDB_NAMESPACE::DBImpl::snapshots ( ) const
inline

db_impl.h 파일의 879 번째 라인에서 정의되었습니다.

879{ return snapshots_; }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ StartBlockCacheTrace() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::StartBlockCacheTrace ( const BlockCacheTraceOptions & options,
std::unique_ptr< BlockCacheTraceWriter > && trace_writer )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6705 번째 라인에서 정의되었습니다.

6707 {
6708 return block_cache_tracer_.StartTrace(trace_options, std::move(trace_writer));
6709}
Status StartTrace(const BlockCacheTraceOptions &trace_options, std::unique_ptr< BlockCacheTraceWriter > &&trace_writer)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ StartBlockCacheTrace() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::StartBlockCacheTrace ( const TraceOptions & trace_options,
std::unique_ptr< TraceWriter > && trace_writer )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6688 번째 라인에서 정의되었습니다.

6690 {
6691 BlockCacheTraceOptions block_trace_opts;
6692 block_trace_opts.sampling_frequency = trace_options.sampling_frequency;
6693
6694 BlockCacheTraceWriterOptions trace_writer_opt;
6695 trace_writer_opt.max_trace_file_size = trace_options.max_trace_file_size;
6696
6697 std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
6698 NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
6699 std::move(trace_writer));
6700
6701 return block_cache_tracer_.StartTrace(block_trace_opts,
6702 std::move(block_cache_trace_writer));
6703}
const std::shared_ptr< SystemClock > & GetSystemClock() const
Definition env.cc:1177
std::unique_ptr< BlockCacheTraceWriter > NewBlockCacheTraceWriter(SystemClock *clock, const BlockCacheTraceWriterOptions &trace_options, std::unique_ptr< TraceWriter > &&trace_writer)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ StartIOTrace()

Status ROCKSDB_NAMESPACE::DBImpl::StartIOTrace ( const TraceOptions & options,
std::unique_ptr< TraceWriter > && trace_writer )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 4483 번째 라인에서 정의되었습니다.

4484 {
4485 assert(trace_writer != nullptr);
4486 return io_tracer_->StartIOTrace(GetSystemClock(), trace_options,
4487 std::move(trace_writer));
4488}
SystemClock * GetSystemClock() const
Definition db_impl.cc:4479
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ StartPeriodicTaskScheduler()

Status ROCKSDB_NAMESPACE::DBImpl::StartPeriodicTaskScheduler ( )
private

db_impl.cc 파일의 799 번째 라인에서 정의되었습니다.

799 {
800#ifndef NDEBUG
801 // It only used by test to disable scheduler
802 bool disable_scheduler = false;
804 "DBImpl::StartPeriodicTaskScheduler:DisableScheduler",
805 &disable_scheduler);
806 if (disable_scheduler) {
807 return Status::OK();
808 }
809
810 {
811 InstrumentedMutexLock l(&mutex_);
812 TEST_SYNC_POINT_CALLBACK("DBImpl::StartPeriodicTaskScheduler:Init",
813 &periodic_task_scheduler_);
814 }
815
816#endif // !NDEBUG
819 PeriodicTaskType::kDumpStats,
820 periodic_task_functions_.at(PeriodicTaskType::kDumpStats),
822 if (!s.ok()) {
823 return s;
824 }
825 }
828 PeriodicTaskType::kPersistStats,
829 periodic_task_functions_.at(PeriodicTaskType::kPersistStats),
831 if (!s.ok()) {
832 return s;
833 }
834 }
835
837 PeriodicTaskType::kFlushInfoLog,
838 periodic_task_functions_.at(PeriodicTaskType::kFlushInfoLog));
839
840 return s;
841}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ StartTrace()

Status ROCKSDB_NAMESPACE::DBImpl::StartTrace ( const TraceOptions & options,
std::unique_ptr< TraceWriter > && trace_writer )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6660 번째 라인에서 정의되었습니다.

6661 {
6662 InstrumentedMutexLock lock(&trace_mutex_);
6663 tracer_.reset(new Tracer(immutable_db_options_.clock, trace_options,
6664 std::move(trace_writer)));
6665 return Status::OK();
6666}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SuggestCompactRange()

Status ROCKSDB_NAMESPACE::DBImpl::SuggestCompactRange ( ColumnFamilyHandle * column_family,
const Slice * begin,
const Slice * end )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl_experimental.cc 파일의 23 번째 라인에서 정의되었습니다.

24 {
25 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
26 auto cfd = cfh->cfd();
27 InternalKey start_key, end_key;
28 if (begin != nullptr) {
29 start_key.SetMinPossibleForUserKey(*begin);
30 }
31 if (end != nullptr) {
32 end_key.SetMaxPossibleForUserKey(*end);
33 }
34 {
35 InstrumentedMutexLock l(&mutex_);
36 auto vstorage = cfd->current()->storage_info();
37 for (int level = 0; level < vstorage->num_non_empty_levels() - 1; ++level) {
38 std::vector<FileMetaData*> inputs;
39 vstorage->GetOverlappingInputs(
40 level, begin == nullptr ? nullptr : &start_key,
41 end == nullptr ? nullptr : &end_key, &inputs);
42 for (auto f : inputs) {
43 f->marked_for_compaction = true;
44 }
45 }
46 // Since we have some more files to compact, we should also recompute
47 // compaction score
48 vstorage->ComputeCompactionScore(*cfd->ioptions(),
49 *cfd->GetLatestMutableCFOptions());
52 }
53 return Status::OK();
54}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SwitchMemtable()

Status ROCKSDB_NAMESPACE::DBImpl::SwitchMemtable ( ColumnFamilyData * cfd,
WriteContext * context,
ReadOnlyMemTable * new_imm = nullptr,
SequenceNumber last_seqno = 0 )
private

db_impl_write.cc 파일의 2385 번째 라인에서 정의되었습니다.

2387 {
2388 mutex_.AssertHeld();
2389 assert(lock_wal_count_ == 0);
2390
2391 // TODO: plumb Env::IOActivity, Env::IOPriority
2392 const WriteOptions write_options;
2393
2394 log::Writer* new_log = nullptr;
2395 MemTable* new_mem = nullptr;
2396 IOStatus io_s;
2397
2398 // Recoverable state is persisted in WAL. After memtable switch, WAL might
2399 // be deleted, so we write the state to memtable to be persisted as well.
2400 Status s = WriteRecoverableState();
2401 if (!s.ok()) {
2402 return s;
2403 }
2404
2405 // Attempt to switch to a new memtable and trigger flush of old.
2406 // Do this without holding the dbmutex lock.
2407 assert(versions_->prev_log_number() == 0);
2408 if (two_write_queues_) {
2410 }
2411 bool creating_new_log = !log_empty_;
2412 if (two_write_queues_) {
2414 }
2415 uint64_t recycle_log_number = 0;
2416 // If file deletion is disabled, don't recycle logs since it'll result in
2417 // the file getting renamed
2418 if (creating_new_log && immutable_db_options_.recycle_log_file_num &&
2420 recycle_log_number = log_recycle_files_.front();
2421 }
2422 uint64_t new_log_number =
2423 creating_new_log ? versions_->NewFileNumber() : logfile_number_;
2424 const MutableCFOptions mutable_cf_options = *cfd->GetLatestMutableCFOptions();
2425
2426 // Set memtable_info for memtable sealed callback
2427 // TODO: memtable_info for `new_imm`
2428 MemTableInfo memtable_info;
2429 memtable_info.cf_name = cfd->GetName();
2430 memtable_info.first_seqno = cfd->mem()->GetFirstSequenceNumber();
2431 memtable_info.earliest_seqno = cfd->mem()->GetEarliestSequenceNumber();
2432 memtable_info.num_entries = cfd->mem()->NumEntries();
2433 memtable_info.num_deletes = cfd->mem()->NumDeletion();
2434 if (!cfd->ioptions()->persist_user_defined_timestamps &&
2435 cfd->user_comparator()->timestamp_size() > 0) {
2436 const Slice& newest_udt = cfd->mem()->GetNewestUDT();
2437 memtable_info.newest_udt.assign(newest_udt.data(), newest_udt.size());
2438 }
2439 // Log this later after lock release. It may be outdated, e.g., if background
2440 // flush happens before logging, but that should be ok.
2441 int num_imm_unflushed = cfd->imm()->NumNotFlushed();
2442 const auto preallocate_block_size =
2443 GetWalPreallocateBlockSize(mutable_cf_options.write_buffer_size);
2444 mutex_.Unlock();
2445 if (creating_new_log) {
2446 // TODO: Write buffer size passed in should be max of all CF's instead
2447 // of mutable_cf_options.write_buffer_size.
2448 io_s = CreateWAL(write_options, new_log_number, recycle_log_number,
2449 preallocate_block_size, &new_log);
2450 if (s.ok()) {
2451 s = io_s;
2452 }
2453 }
2454 if (s.ok()) {
2455 // FIXME: from the comment for GetEarliestSequenceNumber(), any key with
2456 // seqno >= earliest_seqno should be in this or later memtable. This means
2457 // we should use LastSequence() + 1 or last_seqno + 1 here. And it needs to
2458 // be incremented with file ingestion and other operations that consumes
2459 // sequence number.
2460 SequenceNumber seq;
2461 if (new_imm) {
2462 assert(last_seqno > versions_->LastSequence());
2463 seq = last_seqno;
2464 } else {
2465 seq = versions_->LastSequence();
2466 }
2467 new_mem =
2468 cfd->ConstructNewMemtable(mutable_cf_options, /*earliest_seq=*/seq);
2469 context->superversion_context.NewSuperVersion();
2470
2472 "[%s] New memtable created with log file: #%" PRIu64
2473 ". Immutable memtables: %d.\n",
2474 cfd->GetName().c_str(), new_log_number, num_imm_unflushed);
2475 // There should be no concurrent write as the thread is at the front of
2476 // writer queue
2477 cfd->mem()->ConstructFragmentedRangeTombstones();
2478 }
2479
2480 mutex_.Lock();
2481 if (recycle_log_number != 0) {
2482 // Since renaming the file is done outside DB mutex, we need to ensure
2483 // concurrent full purges don't delete the file while we're recycling it.
2484 // To achieve that we hold the old log number in the recyclable list until
2485 // after it has been renamed.
2486 assert(log_recycle_files_.front() == recycle_log_number);
2487 log_recycle_files_.pop_front();
2488 }
2489 if (s.ok() && creating_new_log) {
2490 InstrumentedMutexLock l(&log_write_mutex_);
2491 assert(new_log != nullptr);
2492 if (!logs_.empty()) {
2493 // Alway flush the buffer of the last log before switching to a new one
2494 log::Writer* cur_log_writer = logs_.back().writer;
2496 // In recovery path, we force another try of writing WAL buffer.
2497 cur_log_writer->file()->reset_seen_error();
2498 }
2499 io_s = cur_log_writer->WriteBuffer(write_options);
2500 if (s.ok()) {
2501 s = io_s;
2502 }
2503 if (!s.ok()) {
2505 "[%s] Failed to switch from #%" PRIu64 " to #%" PRIu64
2506 " WAL file\n",
2507 cfd->GetName().c_str(), cur_log_writer->get_log_number(),
2508 new_log_number);
2509 }
2510 }
2511 if (s.ok()) {
2512 logfile_number_ = new_log_number;
2513 log_empty_ = true;
2514 log_dir_synced_ = false;
2515 logs_.emplace_back(logfile_number_, new_log);
2516 alive_log_files_.emplace_back(logfile_number_);
2517 }
2518 }
2519
2520 if (!s.ok()) {
2521 // how do we fail if we're not creating new log?
2522 assert(creating_new_log);
2523 delete new_mem;
2524 delete new_log;
2525 context->superversion_context.new_superversion.reset();
2526 // We may have lost data from the WritableFileBuffer in-memory buffer for
2527 // the current log, so treat it as a fatal error and set bg_error
2528 if (!io_s.ok()) {
2529 error_handler_.SetBGError(io_s, BackgroundErrorReason::kMemTable,
2530 /*wal_related=*/true);
2531 } else {
2532 error_handler_.SetBGError(s, BackgroundErrorReason::kMemTable);
2533 }
2534 // Read back bg_error in order to get the right severity
2536 return s;
2537 }
2538
2539 bool empty_cf_updated = false;
2541 !immutable_db_options_.allow_2pc && creating_new_log) {
2542 // In non-2pc mode, WALs become obsolete if they do not contain unflushed
2543 // data. Updating the empty CF's log number might cause some WALs to become
2544 // obsolete. So we should track the WAL obsoletion event before actually
2545 // updating the empty CF's log number.
2546 uint64_t min_wal_number_to_keep =
2547 versions_->PreComputeMinLogNumberWithUnflushedData(logfile_number_);
2548 if (min_wal_number_to_keep >
2549 versions_->GetWalSet().GetMinWalNumberToKeep()) {
2550 // TODO: plumb Env::IOActivity, Env::IOPriority
2551 const ReadOptions read_options;
2552 // Get a snapshot of the empty column families.
2553 // LogAndApply may release and reacquire db
2554 // mutex, during that period, column family may become empty (e.g. its
2555 // flush succeeds), then it affects the computed min_log_number_to_keep,
2556 // so we take a snapshot for consistency of column family data
2557 // status. If a column family becomes non-empty afterwards, its active log
2558 // should still be the created new log, so the min_log_number_to_keep is
2559 // not affected.
2560 autovector<ColumnFamilyData*> empty_cfs;
2561 for (auto cf : *versions_->GetColumnFamilySet()) {
2562 if (cf->IsEmpty()) {
2563 empty_cfs.push_back(cf);
2564 }
2565 }
2566
2567 VersionEdit wal_deletion;
2568 wal_deletion.DeleteWalsBefore(min_wal_number_to_keep);
2569 s = versions_->LogAndApplyToDefaultColumnFamily(
2570 read_options, write_options, &wal_deletion, &mutex_,
2572 if (!s.ok() && versions_->io_status().IsIOError()) {
2573 error_handler_.SetBGError(versions_->io_status(),
2574 BackgroundErrorReason::kManifestWrite);
2575 }
2576 if (!s.ok()) {
2577 return s;
2578 }
2579
2580 for (auto cf : empty_cfs) {
2581 if (cf->IsEmpty()) {
2582 cf->SetLogNumber(logfile_number_);
2583 // MEMPURGE: No need to change this, because new adds
2584 // should still receive new sequence numbers.
2585 cf->mem()->SetCreationSeq(versions_->LastSequence());
2586 } // cf may become non-empty.
2587 }
2588 empty_cf_updated = true;
2589 }
2590 }
2591 if (!empty_cf_updated) {
2592 for (auto cf : *versions_->GetColumnFamilySet()) {
2593 // all this is just optimization to delete logs that
2594 // are no longer needed -- if CF is empty, that means it
2595 // doesn't need that particular log to stay alive, so we just
2596 // advance the log number. no need to persist this in the manifest
2597 if (cf->IsEmpty()) {
2598 if (creating_new_log) {
2599 cf->SetLogNumber(logfile_number_);
2600 }
2601 cf->mem()->SetCreationSeq(versions_->LastSequence());
2602 }
2603 }
2604 }
2605
2606 cfd->mem()->SetNextLogNumber(logfile_number_);
2607 assert(new_mem != nullptr);
2608 cfd->imm()->Add(cfd->mem(), &context->memtables_to_free_);
2609 if (new_imm) {
2610 // Need to assign memtable id here before SetMemtable() below assigns id to
2611 // the new live memtable
2612 cfd->AssignMemtableID(new_imm);
2613 // NOTE: new_imm and cfd->mem() references the same WAL and has the same
2614 // NextLogNumber(). They should be flushed together. For non-atomic-flush,
2615 // we always try to flush all immutable memtable. For atomic flush, these
2616 // two memtables will be marked eligible for flush in the same call to
2617 // AssignAtomicFlushSeq().
2618 new_imm->SetNextLogNumber(logfile_number_);
2619 cfd->imm()->Add(new_imm, &context->memtables_to_free_);
2620 }
2621 new_mem->Ref();
2622 cfd->SetMemtable(new_mem);
2623 InstallSuperVersionAndScheduleWork(cfd, &context->superversion_context,
2624 mutable_cf_options);
2625
2626 // Notify client that memtable is sealed, now that we have successfully
2627 // installed a new memtable
2628 NotifyOnMemTableSealed(cfd, memtable_info);
2629 // It is possible that we got here without checking the value of i_os, but
2630 // that is okay. If we did, it most likely means that s was already an error.
2631 // In any case, ignore any unchecked error for i_os here.
2632 io_s.PermitUncheckedError();
2633 // We guarantee that if a non-ok status is returned, `new_imm` was not added
2634 // to the db.
2635 assert(s.ok());
2636 return s;
2637}
size_t GetWalPreallocateBlockSize(uint64_t write_buffer_size) const
IOStatus CreateWAL(const WriteOptions &write_options, uint64_t log_file_num, uint64_t recycle_log_number, size_t preallocate_block_size, log::Writer **new_log)
void NotifyOnMemTableSealed(ColumnFamilyData *cfd, const MemTableInfo &mem_table_info)
virtual bool IsFileDeletionsEnabled() const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SwitchWAL()

Status ROCKSDB_NAMESPACE::DBImpl::SwitchWAL ( WriteContext * write_context)
private

db_impl_write.cc 파일의 1893 번째 라인에서 정의되었습니다.

1893 {
1894 mutex_.AssertHeld();
1895 assert(write_context != nullptr);
1896 Status status;
1897
1898 if (alive_log_files_.begin()->getting_flushed) {
1899 return status;
1900 }
1901
1902 auto oldest_alive_log = alive_log_files_.begin()->number;
1903 bool flush_wont_release_oldest_log = false;
1904 if (allow_2pc()) {
1905 auto oldest_log_with_uncommitted_prep =
1907
1908 assert(oldest_log_with_uncommitted_prep == 0 ||
1909 oldest_log_with_uncommitted_prep >= oldest_alive_log);
1910 if (oldest_log_with_uncommitted_prep > 0 &&
1911 oldest_log_with_uncommitted_prep == oldest_alive_log) {
1912 if (unable_to_release_oldest_log_) {
1913 // we already attempted to flush all column families dependent on
1914 // the oldest alive log but the log still contained uncommitted
1915 // transactions so there is still nothing that we can do.
1916 return status;
1917 } else {
1920 "Unable to release oldest log due to uncommitted transaction");
1922 flush_wont_release_oldest_log = true;
1923 }
1924 }
1925 }
1926 if (!flush_wont_release_oldest_log) {
1927 // we only mark this log as getting flushed if we have successfully
1928 // flushed all data in this log. If this log contains outstanding prepared
1929 // transactions then we cannot flush this log until those transactions are
1930 // commited.
1932 alive_log_files_.begin()->getting_flushed = true;
1933 }
1934
1937 "Flushing all column families with data in WAL number %" PRIu64
1938 ". Total log size is %" PRIu64 " while max_total_wal_size is %" PRIu64,
1939 oldest_alive_log, total_log_size_.load(), GetMaxTotalWalSize());
1940 // no need to refcount because drop is happening in write thread, so can't
1941 // happen while we're in the write thread
1942 autovector<ColumnFamilyData*> cfds;
1945 } else {
1946 for (auto cfd : *versions_->GetColumnFamilySet()) {
1947 if (cfd->IsDropped()) {
1948 continue;
1949 }
1950 if (cfd->OldestLogToKeep() <= oldest_alive_log) {
1951 cfds.push_back(cfd);
1952 }
1953 }
1954 MaybeFlushStatsCF(&cfds);
1955 }
1956 WriteThread::Writer nonmem_w;
1957 if (two_write_queues_) {
1958 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
1959 }
1960
1961 for (const auto cfd : cfds) {
1962 cfd->Ref();
1963 status = SwitchMemtable(cfd, write_context);
1964 cfd->UnrefAndTryDelete();
1965 if (!status.ok()) {
1966 break;
1967 }
1968 }
1969 if (two_write_queues_) {
1971 }
1972
1973 if (status.ok()) {
1976 }
1977 for (auto cfd : cfds) {
1978 cfd->imm()->FlushRequested();
1980 FlushRequest flush_req;
1981 GenerateFlushRequest({cfd}, FlushReason::kWalFull, &flush_req);
1982 EnqueuePendingFlush(flush_req);
1983 }
1984 }
1986 FlushRequest flush_req;
1987 GenerateFlushRequest(cfds, FlushReason::kWalFull, &flush_req);
1988 EnqueuePendingFlush(flush_req);
1989 }
1991 }
1992 return status;
1993}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SyncClosedWals()

IOStatus ROCKSDB_NAMESPACE::DBImpl::SyncClosedWals ( const WriteOptions & write_options,
JobContext * job_context,
VersionEdit * synced_wals,
bool error_recovery_in_prog )
private

db_impl_compaction_flush.cc 파일의 127 번째 라인에서 정의되었습니다.

130 {
131 TEST_SYNC_POINT("DBImpl::SyncClosedWals:Start");
132
133 IOStatus io_s = SyncWalImpl(/*include_current_wal*/ false, write_options,
134 job_context, synced_wals, error_recovery_in_prog);
135 if (!io_s.ok()) {
136 TEST_SYNC_POINT("DBImpl::SyncClosedWals:Failed");
137 } else {
138 TEST_SYNC_POINT("DBImpl::SyncClosedWals:end");
139 }
140 return io_s;
141}
IOStatus SyncWalImpl(bool include_current_wal, const WriteOptions &write_options, JobContext *job_context, VersionEdit *synced_wals, bool error_recovery_in_prog)
Definition db_impl.cc:1616
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SyncWAL()

Status ROCKSDB_NAMESPACE::DBImpl::SyncWAL ( )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl.cc 파일의 1597 번째 라인에서 정의되었습니다.

1597 {
1598 TEST_SYNC_POINT("DBImpl::SyncWAL:Begin");
1599 WriteOptions write_options;
1600 VersionEdit synced_wals;
1601 Status s = SyncWalImpl(/*include_current_wal=*/true, write_options,
1602 /*job_context=*/nullptr, &synced_wals,
1603 /*error_recovery_in_prog=*/false);
1604
1605 if (s.ok() && synced_wals.IsWalAddition()) {
1606 InstrumentedMutexLock l(&mutex_);
1607 // TODO: plumb Env::IOActivity, Env::IOPriority
1608 const ReadOptions read_options;
1609 s = ApplyWALToManifest(read_options, write_options, &synced_wals);
1610 }
1611
1612 TEST_SYNC_POINT("DBImpl::SyncWAL:BeforeMarkLogsSynced:2");
1613 return s;
1614}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SyncWalImpl()

IOStatus ROCKSDB_NAMESPACE::DBImpl::SyncWalImpl ( bool include_current_wal,
const WriteOptions & write_options,
JobContext * job_context,
VersionEdit * synced_wals,
bool error_recovery_in_prog )
private

db_impl.cc 파일의 1616 번째 라인에서 정의되었습니다.

1619 {
1620 autovector<log::Writer*, 1> wals_to_sync;
1621 bool need_wal_dir_sync;
1622 // Number of a WAL that was active at the start of call and maybe is by
1623 // the end of the call.
1624 uint64_t maybe_active_number;
1625 // Sync WALs up to this number
1626 uint64_t up_to_number;
1627
1628 {
1629 InstrumentedMutexLock l(&log_write_mutex_);
1630 assert(!logs_.empty());
1631
1632 maybe_active_number = logfile_number_;
1633 up_to_number =
1634 include_current_wal ? maybe_active_number : maybe_active_number - 1;
1635
1636 while (logs_.front().number <= up_to_number && logs_.front().IsSyncing()) {
1638 }
1639 // First check that logs are safe to sync in background.
1640 if (include_current_wal &&
1641 !logs_.back().writer->file()->writable_file()->IsSyncThreadSafe()) {
1642 return IOStatus::NotSupported(
1643 "SyncWAL() is not supported for this implementation of WAL file",
1645 ? "try setting Options::allow_mmap_writes to false"
1646 : Slice());
1647 }
1648 for (auto it = logs_.begin();
1649 it != logs_.end() && it->number <= up_to_number; ++it) {
1650 auto& log = *it;
1651 // Ensure the head of logs_ is marked as getting_synced if any is.
1652 log.PrepareForSync();
1653 // If last sync failed on a later WAL, this could be a fully synced
1654 // and closed WAL that just needs to be recorded as synced in the
1655 // manifest.
1656 if (log.writer->file()) {
1657 wals_to_sync.push_back(log.writer);
1658 }
1659 }
1660
1661 need_wal_dir_sync = !log_dir_synced_;
1662 }
1663
1664 if (include_current_wal) {
1665 TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:1");
1666 }
1667 RecordTick(stats_, WAL_FILE_SYNCED);
1668 IOOptions opts;
1669 IOStatus io_s = WritableFileWriter::PrepareIOOptions(write_options, opts);
1670 std::list<log::Writer*> wals_internally_closed;
1671 if (io_s.ok()) {
1672 for (log::Writer* log : wals_to_sync) {
1673 if (job_context) {
1675 "[JOB %d] Syncing log #%" PRIu64, job_context->job_id,
1676 log->get_log_number());
1677 }
1678 if (error_recovery_in_prog) {
1679 log->file()->reset_seen_error();
1680 }
1681 if (log->get_log_number() >= maybe_active_number) {
1682 assert(log->get_log_number() == maybe_active_number);
1683 io_s = log->file()->SyncWithoutFlush(opts,
1685 } else {
1686 io_s = log->file()->Sync(opts, immutable_db_options_.use_fsync);
1687 }
1688 if (!io_s.ok()) {
1689 break;
1690 }
1691 // WALs can be closed when purging obsolete files, but if recycling is
1692 // enabled, the log file is closed here so that it can be reused. And
1693 // immediate closure here upon final sync makes it easier to guarantee
1694 // that Checkpoint doesn't LinkFile on a WAL still open for write, which
1695 // might be unsupported for some FileSystem implementations. Close here
1696 // should be inexpensive because flush and sync are done, so the kill
1697 // switch background_close_inactive_wals is expected to be removed in
1698 // the future.
1699 if (log->get_log_number() < maybe_active_number &&
1702 if (error_recovery_in_prog) {
1703 log->file()->reset_seen_error();
1704 }
1705 io_s = log->file()->Close(opts);
1706 wals_internally_closed.push_back(log);
1707 if (!io_s.ok()) {
1708 break;
1709 }
1710 }
1711 }
1712 }
1713 if (!io_s.ok()) {
1714 ROCKS_LOG_ERROR(immutable_db_options_.info_log, "WAL Sync error %s",
1715 io_s.ToString().c_str());
1716 // In case there is a fs error we should set it globally to prevent the
1717 // future writes
1718 WALIOStatusCheck(io_s);
1719 }
1720 if (io_s.ok() && need_wal_dir_sync) {
1722 IOOptions(), nullptr,
1723 DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
1724 }
1725 if (include_current_wal) {
1726 TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:2");
1727
1728 TEST_SYNC_POINT("DBImpl::SyncWAL:BeforeMarkLogsSynced:1");
1729 } else {
1730 TEST_SYNC_POINT_CALLBACK("DBImpl::SyncClosedWals:BeforeReLock",
1731 /*arg=*/nullptr);
1732 }
1733 {
1734 InstrumentedMutexLock l(&log_write_mutex_);
1735 for (auto* wal : wals_internally_closed) {
1736 // We can only modify the state of log::Writer under the mutex
1737 bool was_closed = wal->PublishIfClosed();
1738 assert(was_closed);
1739 (void)was_closed;
1740 }
1741 if (io_s.ok()) {
1742 MarkLogsSynced(up_to_number, need_wal_dir_sync, synced_wals);
1743 } else {
1744 MarkLogsNotSynced(up_to_number);
1745 }
1746 }
1747 return io_s;
1748}
FSDirectory * GetWalDir()
Definition db_impl.h:107
virtual IOStatus FsyncWithDirOptions(const IOOptions &options, IODebugContext *dbg, const DirFsyncOptions &)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TablesRangeTombstoneSummary()

Status ROCKSDB_NAMESPACE::DBImpl::TablesRangeTombstoneSummary ( ColumnFamilyHandle * column_family,
int max_entries_to_print,
std::string * out_str )

db_impl.cc 파일의 1237 번째 라인에서 정의되었습니다.

1239 {
1240 auto* cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
1241 ColumnFamilyData* cfd = cfh->cfd();
1242
1243 SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
1244 Version* version = super_version->current;
1245
1246 Status s =
1247 version->TablesRangeTombstoneSummary(max_entries_to_print, out_str);
1248
1249 CleanupSuperVersion(super_version);
1250 return s;
1251}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_AtomicFlushMemTables()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_AtomicFlushMemTables ( const autovector< ColumnFamilyData * > & provided_candidate_cfds,
const FlushOptions & flush_opts )

db_impl_debug.cc 파일의 158 번째 라인에서 정의되었습니다.

160 {
161 return AtomicFlushMemTables(flush_opts, FlushReason::kTest,
162 provided_candidate_cfds);
163}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_BeginWrite()

void * ROCKSDB_NAMESPACE::DBImpl::TEST_BeginWrite ( )

db_impl_debug.cc 파일의 214 번째 라인에서 정의되었습니다.

214 {
215 auto w = new WriteThread::Writer();
216 write_thread_.EnterUnbatched(w, &mutex_);
217 return static_cast<void*>(w);
218}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_BGCompactionsAllowed()

int ROCKSDB_NAMESPACE::DBImpl::TEST_BGCompactionsAllowed ( ) const

db_impl_debug.cc 파일의 274 번째 라인에서 정의되었습니다.

274 {
275 InstrumentedMutexLock l(&mutex_);
277}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_BGFlushesAllowed()

int ROCKSDB_NAMESPACE::DBImpl::TEST_BGFlushesAllowed ( ) const

db_impl_debug.cc 파일의 279 번째 라인에서 정의되었습니다.

279 {
280 InstrumentedMutexLock l(&mutex_);
282}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_CompactRange()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_CompactRange ( int level,
const Slice * begin,
const Slice * end,
ColumnFamilyHandle * column_family = nullptr,
bool disallow_trivial_move = false )

db_impl_debug.cc 파일의 94 번째 라인에서 정의되었습니다.

97 {
98 ColumnFamilyData* cfd;
99 if (column_family == nullptr) {
100 cfd = default_cf_handle_->cfd();
101 } else {
102 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
103 cfd = cfh->cfd();
104 }
105 int output_level =
106 (cfd->ioptions()->compaction_style == kCompactionStyleUniversal ||
107 cfd->ioptions()->compaction_style == kCompactionStyleFIFO)
108 ? level
109 : level + 1;
110 return RunManualCompaction(
111 cfd, level, output_level, CompactRangeOptions(), begin, end, true,
112 disallow_trivial_move,
113 std::numeric_limits<uint64_t>::max() /*max_file_num_to_ignore*/,
114 "" /*trim_ts*/);
115}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_Current_Manifest_FileNo()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_Current_Manifest_FileNo ( )

db_impl_debug.cc 파일의 86 번째 라인에서 정의되었습니다.

86 {
87 return versions_->manifest_file_number();
88}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_Current_Next_FileNo()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_Current_Next_FileNo ( )

db_impl_debug.cc 파일의 90 번째 라인에서 정의되었습니다.

90 {
91 return versions_->current_next_file_number();
92}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_DeleteObsoleteFiles()

void ROCKSDB_NAMESPACE::DBImpl::TEST_DeleteObsoleteFiles ( )

db_impl_debug.cc 파일의 316 번째 라인에서 정의되었습니다.

316 {
317 InstrumentedMutexLock l(&mutex_);
319}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_EndWrite()

void ROCKSDB_NAMESPACE::DBImpl::TEST_EndWrite ( void * w)

db_impl_debug.cc 파일의 220 번째 라인에서 정의되었습니다.

220 {
221 auto writer = static_cast<WriteThread::Writer*>(w);
223 delete writer;
224}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_EstimateInMemoryStatsHistorySize()

size_t ROCKSDB_NAMESPACE::DBImpl::TEST_EstimateInMemoryStatsHistorySize ( ) const

db_impl_debug.cc 파일의 321 번째 라인에서 정의되었습니다.

321 {
322 InstrumentedMutexLock l(&const_cast<DBImpl*>(this)->stats_history_mutex_);
324}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_FindMinLogContainingOutstandingPrep()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_FindMinLogContainingOutstandingPrep ( )

db_impl_debug.cc 파일의 248 번째 라인에서 정의되었습니다.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_FindMinPrepLogReferencedByMemTable()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_FindMinPrepLogReferencedByMemTable ( )

db_impl_debug.cc 파일의 260 번째 라인에서 정의되었습니다.

260 {
261 autovector<ReadOnlyMemTable*> empty_list;
262 return FindMinPrepLogReferencedByMemTable(versions_.get(), empty_list);
263}
uint64_t FindMinPrepLogReferencedByMemTable(VersionSet *vset, const autovector< ReadOnlyMemTable * > &memtables_to_flush)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_FlushMemTable() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::TEST_FlushMemTable ( bool wait = true,
bool allow_write_stall = false,
ColumnFamilyHandle * cfh = nullptr )

db_impl_debug.cc 파일의 138 번째 라인에서 정의되었습니다.

139 {
140 FlushOptions fo;
141 fo.wait = wait;
142 fo.allow_write_stall = allow_write_stall;
143 ColumnFamilyData* cfd;
144 if (cfh == nullptr) {
145 cfd = default_cf_handle_->cfd();
146 } else {
147 auto cfhi = static_cast_with_check<ColumnFamilyHandleImpl>(cfh);
148 cfd = cfhi->cfd();
149 }
150 return FlushMemTable(cfd, fo, FlushReason::kTest);
151}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_FlushMemTable() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::TEST_FlushMemTable ( ColumnFamilyData * cfd,
const FlushOptions & flush_opts )

db_impl_debug.cc 파일의 153 번째 라인에서 정의되었습니다.

154 {
155 return FlushMemTable(cfd, flush_opts, FlushReason::kTest);
156}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetAllBlockCaches()

void ROCKSDB_NAMESPACE::DBImpl::TEST_GetAllBlockCaches ( std::unordered_set< const Cache * > * cache_set)

db_impl_debug.cc 파일의 236 번째 라인에서 정의되었습니다.

237 {
238 InstrumentedMutexLock l(&mutex_);
239 for (auto cfd : *versions_->GetColumnFamilySet()) {
240 if (const auto bbto =
241 cfd->GetCurrentMutableCFOptions()
242 ->table_factory->GetOptions<BlockBasedTableOptions>()) {
243 cache_set->insert(bbto->block_cache.get());
244 }
245 }
246}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetBGError()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_GetBGError ( )

db_impl_debug.cc 파일의 198 번째 라인에서 정의되었습니다.

198 {
199 InstrumentedMutexLock l(&mutex_);
200 return error_handler_.GetBGError();
201}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetCurrentLogNumber()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_GetCurrentLogNumber ( ) const
inline

db_impl.h 파일의 1226 번째 라인에서 정의되었습니다.

1226 {
1227 InstrumentedMutexLock l(mutex());
1228 assert(!logs_.empty());
1229 return logs_.back().number;
1230 }

◆ TEST_GetFilesGrabbedForPurge()

const std::unordered_set< uint64_t > & ROCKSDB_NAMESPACE::DBImpl::TEST_GetFilesGrabbedForPurge ( ) const
inline

db_impl.h 파일의 1234 번째 라인에서 정의되었습니다.

1234 {
1236 }

◆ TEST_GetFilesMetaData()

void ROCKSDB_NAMESPACE::DBImpl::TEST_GetFilesMetaData ( ColumnFamilyHandle * column_family,
std::vector< std::vector< FileMetaData > > * metadata,
std::vector< std::shared_ptr< BlobFileMetaData > > * blob_metadata = nullptr )

db_impl_debug.cc 파일의 48 번째 라인에서 정의되었습니다.

51 {
52 assert(metadata);
53
54 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
55 assert(cfh);
56
57 auto cfd = cfh->cfd();
58 assert(cfd);
59
60 InstrumentedMutexLock l(&mutex_);
61
62 const auto* current = cfd->current();
63 assert(current);
64
65 const auto* vstorage = current->storage_info();
66 assert(vstorage);
67
68 metadata->resize(NumberLevels());
69
70 for (int level = 0; level < NumberLevels(); ++level) {
71 const std::vector<FileMetaData*>& files = vstorage->LevelFiles(level);
72
73 (*metadata)[level].clear();
74 (*metadata)[level].reserve(files.size());
75
76 for (const auto& f : files) {
77 (*metadata)[level].push_back(*f);
78 }
79 }
80
81 if (blob_metadata) {
82 *blob_metadata = vstorage->GetBlobFiles();
83 }
84}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetFilesToQuarantine()

const autovector< uint64_t > & ROCKSDB_NAMESPACE::DBImpl::TEST_GetFilesToQuarantine ( ) const

db_impl_debug.cc 파일의 311 번째 라인에서 정의되었습니다.

311 {
312 InstrumentedMutexLock l(&mutex_);
314}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetLastVisibleSequence()

SequenceNumber ROCKSDB_NAMESPACE::DBImpl::TEST_GetLastVisibleSequence ( ) const

db_impl_debug.cc 파일의 284 번째 라인에서 정의되었습니다.

284 {
285 if (last_seq_same_as_publish_seq_) {
286 return versions_->LastSequence();
287 } else {
288 return versions_->LastAllocatedSequence();
289 }
290}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetLatestMutableCFOptions()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_GetLatestMutableCFOptions ( ColumnFamilyHandle * column_family,
MutableCFOptions * mutable_cf_options )

db_impl_debug.cc 파일의 265 번째 라인에서 정의되었습니다.

266 {
267 InstrumentedMutexLock l(&mutex_);
268
269 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
270 *mutable_cf_options = *cfh->cfd()->GetLatestMutableCFOptions();
271 return Status::OK();
272}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetLevel0TotalSize()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_GetLevel0TotalSize ( )

db_impl_debug.cc 파일의 21 번째 라인에서 정의되었습니다.

21 {
22 InstrumentedMutexLock l(&mutex_);
24}
uint64_t NumLevelBytes(int level) const
VersionStorageInfo * storage_info()
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetPeriodicTaskScheduler()

const PeriodicTaskScheduler & ROCKSDB_NAMESPACE::DBImpl::TEST_GetPeriodicTaskScheduler ( ) const

db_impl_debug.cc 파일의 302 번째 라인에서 정의되었습니다.

302 {
304}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetSeqnoToTimeMapping()

SeqnoToTimeMapping ROCKSDB_NAMESPACE::DBImpl::TEST_GetSeqnoToTimeMapping ( ) const

db_impl_debug.cc 파일의 306 번째 라인에서 정의되었습니다.

306 {
307 InstrumentedMutexLock l(&mutex_);
309}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_GetWalPreallocateBlockSize()

size_t ROCKSDB_NAMESPACE::DBImpl::TEST_GetWalPreallocateBlockSize ( uint64_t write_buffer_size) const

db_impl_debug.cc 파일의 292 번째 라인에서 정의되었습니다.

293 {
294 InstrumentedMutexLock l(&mutex_);
295 return GetWalPreallocateBlockSize(write_buffer_size);
296}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_IsLogGettingFlushed()

bool ROCKSDB_NAMESPACE::DBImpl::TEST_IsLogGettingFlushed ( )
inline

db_impl.h 파일의 1120 번째 라인에서 정의되었습니다.

1120 {
1121 return alive_log_files_.begin()->getting_flushed;
1122 }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_IsRecoveryInProgress()

bool ROCKSDB_NAMESPACE::DBImpl::TEST_IsRecoveryInProgress ( )

db_impl_debug.cc 파일의 203 번째 라인에서 정의되었습니다.

203 {
204 InstrumentedMutexLock l(&mutex_);
206}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_LockMutex()

void ROCKSDB_NAMESPACE::DBImpl::TEST_LockMutex ( )

db_impl_debug.cc 파일의 208 번째 라인에서 정의되었습니다.

208{ mutex_.Lock(); }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_LogfileNumber()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_LogfileNumber ( )

db_impl_debug.cc 파일의 231 번째 라인에서 정의되었습니다.

231 {
232 InstrumentedMutexLock l(&mutex_);
233 return logfile_number_;
234}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_LogsToFreeSize()

size_t ROCKSDB_NAMESPACE::DBImpl::TEST_LogsToFreeSize ( )

db_impl_debug.cc 파일의 226 번째 라인에서 정의되었습니다.

226 {
227 InstrumentedMutexLock l(&log_write_mutex_);
228 return logs_to_free_.size();
229}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_LogsWithPrepSize()

size_t ROCKSDB_NAMESPACE::DBImpl::TEST_LogsWithPrepSize ( )

db_impl_debug.cc 파일의 256 번째 라인에서 정의되었습니다.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_MaxNextLevelOverlappingBytes()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_MaxNextLevelOverlappingBytes ( ColumnFamilyHandle * column_family = nullptr)

db_impl_debug.cc 파일의 35 번째 라인에서 정의되었습니다.

36 {
37 ColumnFamilyData* cfd;
38 if (column_family == nullptr) {
39 cfd = default_cf_handle_->cfd();
40 } else {
41 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
42 cfd = cfh->cfd();
43 }
44 InstrumentedMutexLock l(&mutex_);
45 return cfd->current()->storage_info()->MaxNextLevelOverlappingBytes();
46}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_MaxTotalInMemoryState()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_MaxTotalInMemoryState ( ) const
inline

db_impl.h 파일의 1193 번째 라인에서 정의되었습니다.

1193 {
1195 }

◆ TEST_Mutex()

InstrumentedMutex * ROCKSDB_NAMESPACE::DBImpl::TEST_Mutex ( )
inline

db_impl.h 파일의 1182 번째 라인에서 정의되었습니다.

1182{ return &mutex_; }

◆ TEST_PreparedSectionCompletedSize()

size_t ROCKSDB_NAMESPACE::DBImpl::TEST_PreparedSectionCompletedSize ( )

db_impl_debug.cc 파일의 252 번째 라인에서 정의되었습니다.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_ResetDbSessionIdGen()

void ROCKSDB_NAMESPACE::DBImpl::TEST_ResetDbSessionIdGen ( )
static

db_impl.cc 파일의 5259 번째 라인에서 정의되었습니다.

5259{ DbSessionIdGen()->Reset(); }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_SignalAllBgCv()

void ROCKSDB_NAMESPACE::DBImpl::TEST_SignalAllBgCv ( )

db_impl_debug.cc 파일의 212 번째 라인에서 정의되었습니다.

212{ bg_cv_.SignalAll(); }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_SwitchMemtable()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_SwitchMemtable ( ColumnFamilyData * cfd = nullptr)

db_impl_debug.cc 파일의 117 번째 라인에서 정의되었습니다.

117 {
118 WriteContext write_context;
119 InstrumentedMutexLock l(&mutex_);
120 if (cfd == nullptr) {
121 cfd = default_cf_handle_->cfd();
122 }
123
124 Status s;
125 void* writer = TEST_BeginWrite();
126 if (two_write_queues_) {
127 WriteThread::Writer nonmem_w;
128 nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
129 s = SwitchMemtable(cfd, &write_context);
131 } else {
132 s = SwitchMemtable(cfd, &write_context);
133 }
134 TEST_EndWrite(writer);
135 return s;
136}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_SwitchWAL()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_SwitchWAL ( )

db_impl_debug.cc 파일의 26 번째 라인에서 정의되었습니다.

26 {
27 WriteContext write_context;
28 InstrumentedMutexLock l(&mutex_);
29 void* writer = TEST_BeginWrite();
30 auto s = SwitchWAL(&write_context);
31 TEST_EndWrite(writer);
32 return s;
33}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_table_cache()

Cache * ROCKSDB_NAMESPACE::DBImpl::TEST_table_cache ( )
inline

db_impl.h 파일의 1209 번째 라인에서 정의되었습니다.

1209{ return table_cache_.get(); }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_total_log_size()

uint64_t ROCKSDB_NAMESPACE::DBImpl::TEST_total_log_size ( ) const
inline

db_impl.h 파일의 1201 번째 라인에서 정의되었습니다.

1201{ return total_log_size_; }

◆ TEST_UnableToReleaseOldestLog()

bool ROCKSDB_NAMESPACE::DBImpl::TEST_UnableToReleaseOldestLog ( )
inline

db_impl.h 파일의 1118 번째 라인에서 정의되었습니다.

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_UnlockMutex()

void ROCKSDB_NAMESPACE::DBImpl::TEST_UnlockMutex ( )

db_impl_debug.cc 파일의 210 번째 라인에서 정의되었습니다.

210{ mutex_.Unlock(); }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_ValidateOptions()

static Status ROCKSDB_NAMESPACE::DBImpl::TEST_ValidateOptions ( const DBOptions & db_options)
inlinestatic

db_impl.h 파일의 1240 번째 라인에서 정의되었습니다.

1240 {
1241 return ValidateOptions(db_options);
1242 }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_VerifyNoObsoleteFilesCached()

void ROCKSDB_NAMESPACE::DBImpl::TEST_VerifyNoObsoleteFilesCached ( bool db_mutex_already_held) const

db_impl_debug.cc 파일의 326 번째 라인에서 정의되었습니다.

327 {
328 // This check is somewhat expensive and obscure to make a part of every
329 // unit test in every build variety. Thus, we only enable it for ASAN builds.
331 return;
332 }
333
334 std::optional<InstrumentedMutexLock> l;
335 if (db_mutex_already_held) {
336 mutex_.AssertHeld();
337 } else {
338 l.emplace(&mutex_);
339 }
340
341 if (!opened_successfully_) {
342 // We don't need to pro-actively clean up open files during DB::Open()
343 // if we know we are about to fail and clean up in Close().
344 return;
345 }
346 if (disable_delete_obsolete_files_ > 0) {
347 // For better or worse, DB::Close() is allowed with deletions disabled.
348 // Since we generally associate clean-up of open files with deleting them,
349 // we allow "obsolete" open files when deletions are disabled.
350 return;
351 }
352
353 // Live and "quarantined" files are allowed to be open in table cache
354 std::set<uint64_t> live_and_quar_files;
355 for (auto cfd : *versions_->GetColumnFamilySet()) {
356 if (cfd->IsDropped()) {
357 continue;
358 }
359 // Iterate over live versions
360 Version* current = cfd->current();
361 Version* ver = current;
362 do {
363 // Sneakily add both SST and blob files to the same list
364 std::vector<uint64_t> live_files_vec;
365 ver->AddLiveFiles(&live_files_vec, &live_files_vec);
366 live_and_quar_files.insert(live_files_vec.begin(), live_files_vec.end());
367
368 ver = ver->Next();
369 } while (ver != current);
370 }
371 {
372 const auto& quar_files = error_handler_.GetFilesToQuarantine();
373 live_and_quar_files.insert(quar_files.begin(), quar_files.end());
374 }
375 auto fn = [&live_and_quar_files](const Slice& key, Cache::ObjectPtr, size_t,
376 const Cache::CacheItemHelper*) {
377 // See TableCache and BlobFileCache
378 assert(key.size() == sizeof(uint64_t));
379 uint64_t file_number;
380 GetUnaligned(reinterpret_cast<const uint64_t*>(key.data()), &file_number);
381 // Assert file is in live/quarantined set
382 if (live_and_quar_files.find(file_number) == live_and_quar_files.end()) {
383 std::cerr << "File " << file_number << " is not live nor quarantined"
384 << std::endl;
385 assert(false);
386 }
387 };
388 table_cache_->ApplyToAllEntries(fn, {});
389}
constexpr bool kMustFreeHeapAllocations
Definition lang.h:54
void GetUnaligned(const T *memory, T *value)
Definition coding.h:376
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_WaitForBackgroundWork()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_WaitForBackgroundWork ( )

db_impl_debug.cc 파일의 165 번째 라인에서 정의되었습니다.

165 {
166 InstrumentedMutexLock l(&mutex_);
168 return error_handler_.GetBGError();
169}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_WaitForCompact() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::TEST_WaitForCompact ( )

db_impl_debug.cc 파일의 182 번째 라인에서 정의되었습니다.

182 {
183 return WaitForCompact(WaitForCompactOptions());
184}
Status WaitForCompact(const WaitForCompactOptions &wait_for_compact_options) override
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_WaitForCompact() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::TEST_WaitForCompact ( const WaitForCompactOptions & wait_for_compact_options)

db_impl_debug.cc 파일의 185 번째 라인에서 정의되었습니다.

186 {
187 return WaitForCompact(wait_for_compact_options);
188}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_WaitForFlushMemTable()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_WaitForFlushMemTable ( ColumnFamilyHandle * column_family = nullptr)

db_impl_debug.cc 파일의 171 번째 라인에서 정의되었습니다.

171 {
172 ColumnFamilyData* cfd;
173 if (column_family == nullptr) {
174 cfd = default_cf_handle_->cfd();
175 } else {
176 auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
177 cfd = cfh->cfd();
178 }
179 return WaitForFlushMemTable(cfd, nullptr, false);
180}
Status WaitForFlushMemTable(ColumnFamilyData *cfd, const uint64_t *flush_memtable_id=nullptr, bool resuming_from_bg_err=false, std::optional< FlushReason > flush_reason=std::nullopt)
Definition db_impl.h:2137
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_WaitForPeriodicTaskRun()

void ROCKSDB_NAMESPACE::DBImpl::TEST_WaitForPeriodicTaskRun ( std::function< void()> callback) const

db_impl_debug.cc 파일의 298 번째 라인에서 정의되었습니다.

298 {
300}
void TEST_WaitForRun(const std::function< void()> &callback) const
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_WaitForPurge()

Status ROCKSDB_NAMESPACE::DBImpl::TEST_WaitForPurge ( )

db_impl_debug.cc 파일의 190 번째 라인에서 정의되었습니다.

190 {
191 InstrumentedMutexLock l(&mutex_);
192 while (bg_purge_scheduled_ && error_handler_.GetBGError().ok()) {
193 bg_cv_.Wait();
194 }
195 return error_handler_.GetBGError();
196}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TEST_write_controler()

WriteController & ROCKSDB_NAMESPACE::DBImpl::TEST_write_controler ( )
inline

db_impl.h 파일의 1211 번째 라인에서 정의되었습니다.

1211{ return write_controller_; }

◆ ThrottleLowPriWritesIfNeeded()

Status ROCKSDB_NAMESPACE::DBImpl::ThrottleLowPriWritesIfNeeded ( const WriteOptions & write_options,
WriteBatch * my_batch )
private

db_impl_write.cc 파일의 2223 번째 라인에서 정의되었습니다.

2224 {
2225 assert(write_options.low_pri);
2226 // This is called outside the DB mutex. Although it is safe to make the call,
2227 // the consistency condition is not guaranteed to hold. It's OK to live with
2228 // it in this case.
2229 // If we need to speed compaction, it means the compaction is left behind
2230 // and we start to limit low pri writes to a limit.
2232 if (allow_2pc() && (my_batch->HasCommit() || my_batch->HasRollback())) {
2233 // For 2PC, we only rate limit prepare, not commit.
2234 return Status::OK();
2235 }
2236 if (write_options.no_slowdown) {
2237 return Status::Incomplete("Low priority write stall");
2238 } else {
2239 assert(my_batch != nullptr);
2240 // Rate limit those writes. The reason that we don't completely wait
2241 // is that in case the write is heavy, low pri writes may never have
2242 // a chance to run. Now we guarantee we are still slowly making
2243 // progress.
2244 PERF_TIMER_FOR_WAIT_GUARD(write_delay_time);
2245 auto data_size = my_batch->GetDataSize();
2246 while (data_size > 0) {
2248 data_size, 0 /* alignment */, Env::IO_HIGH, nullptr /* stats */,
2249 RateLimiter::OpType::kWrite);
2250 data_size -= allowed;
2251 }
2252 }
2253 }
2254 return Status::OK();
2255}
virtual size_t RequestToken(size_t bytes, size_t alignment, Env::IOPriority io_priority, Statistics *stats, RateLimiter::OpType op_type)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TraceIteratorSeek()

Status ROCKSDB_NAMESPACE::DBImpl::TraceIteratorSeek ( const uint32_t & cf_id,
const Slice & key,
const Slice & lower_bound,
const Slice upper_bound )

db_impl.cc 파일의 6716 번째 라인에서 정의되었습니다.

6718 {
6719 Status s;
6720 if (tracer_) {
6721 InstrumentedMutexLock lock(&trace_mutex_);
6722 if (tracer_) {
6723 s = tracer_->IteratorSeek(cf_id, key, lower_bound, upper_bound);
6724 }
6725 }
6726 return s;
6727}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TraceIteratorSeekForPrev()

Status ROCKSDB_NAMESPACE::DBImpl::TraceIteratorSeekForPrev ( const uint32_t & cf_id,
const Slice & key,
const Slice & lower_bound,
const Slice upper_bound )

db_impl.cc 파일의 6729 번째 라인에서 정의되었습니다.

6731 {
6732 Status s;
6733 if (tracer_) {
6734 InstrumentedMutexLock lock(&trace_mutex_);
6735 if (tracer_) {
6736 s = tracer_->IteratorSeekForPrev(cf_id, key, lower_bound, upper_bound);
6737 }
6738 }
6739 return s;
6740}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TrackExistingDataFiles()

void ROCKSDB_NAMESPACE::DBImpl::TrackExistingDataFiles ( const std::vector< std::string > & existing_data_files)
protected

db_impl_open.cc 파일의 2010 번째 라인에서 정의되었습니다.

2011 {
2012 TrackOrUntrackFiles(existing_data_files, /*track=*/true);
2013}
void TrackOrUntrackFiles(const std::vector< std::string > &existing_data_files, bool track)
Definition db_impl.cc:6861
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TrackOrUntrackFiles()

void ROCKSDB_NAMESPACE::DBImpl::TrackOrUntrackFiles ( const std::vector< std::string > & existing_data_files,
bool track )
private

db_impl.cc 파일의 6861 번째 라인에서 정의되었습니다.

6862 {
6863 auto sfm = static_cast_with_check<SstFileManagerImpl>(
6865 assert(sfm);
6866 std::vector<ColumnFamilyMetaData> metadata;
6867 GetAllColumnFamilyMetaData(&metadata);
6868 auto action = [&](const std::string& file_path,
6869 std::optional<uint64_t> size) {
6870 if (track) {
6871 if (size) {
6872 sfm->OnAddFile(file_path, *size).PermitUncheckedError();
6873 } else {
6874 sfm->OnAddFile(file_path).PermitUncheckedError();
6875 }
6876 } else {
6877 sfm->OnUntrackFile(file_path).PermitUncheckedError();
6878 }
6879 };
6880
6881 std::unordered_set<std::string> referenced_files;
6882 for (const auto& md : metadata) {
6883 for (const auto& lmd : md.levels) {
6884 for (const auto& fmd : lmd.files) {
6885 // We're assuming that each sst file name exists in at most one of
6886 // the paths.
6887 std::string file_path =
6888 fmd.directory + kFilePathSeparator + fmd.relative_filename;
6889 action(file_path, fmd.size);
6890 referenced_files.insert(file_path);
6891 }
6892 }
6893 for (const auto& bmd : md.blob_files) {
6894 std::string name = bmd.blob_file_name;
6895 // The BlobMetaData.blob_file_name may start with "/".
6896 if (!name.empty() && name[0] == kFilePathSeparator) {
6897 name = name.substr(1);
6898 }
6899 // We're assuming that each blob file name exists in at most one of
6900 // the paths.
6901 std::string file_path = bmd.blob_file_path + kFilePathSeparator + name;
6902 action(file_path, bmd.blob_file_size);
6903 referenced_files.insert(file_path);
6904 }
6905 }
6906
6907 for (const auto& file_path : existing_data_files) {
6908 if (referenced_files.find(file_path) != referenced_files.end()) {
6909 continue;
6910 }
6911 // There shouldn't be any duplicated files. In case there is, SstFileManager
6912 // will take care of deduping it.
6913 action(file_path, /*size=*/std::nullopt);
6914 }
6915}
void GetAllColumnFamilyMetaData(std::vector< ColumnFamilyMetaData > *metadata) override
Definition db_impl.cc:5134
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TrimMemtableHistory()

Status ROCKSDB_NAMESPACE::DBImpl::TrimMemtableHistory ( WriteContext * context)
private

db_impl_write.cc 파일의 2291 번째 라인에서 정의되었습니다.

2291 {
2292 autovector<ColumnFamilyData*> cfds;
2293 ColumnFamilyData* tmp_cfd;
2294 while ((tmp_cfd = trim_history_scheduler_.TakeNextColumnFamily()) !=
2295 nullptr) {
2296 cfds.push_back(tmp_cfd);
2297 }
2298 for (auto& cfd : cfds) {
2299 autovector<MemTable*> to_delete;
2300 bool trimmed = cfd->imm()->TrimHistory(&context->memtables_to_free_,
2301 cfd->mem()->MemoryAllocatedBytes());
2302 if (trimmed) {
2303 context->superversion_context.NewSuperVersion();
2304 assert(context->superversion_context.new_superversion.get() != nullptr);
2305 cfd->InstallSuperVersion(&context->superversion_context, &mutex_);
2306 }
2307
2308 if (cfd->UnrefAndTryDelete()) {
2309 cfd = nullptr;
2310 }
2311 }
2312 return Status::OK();
2313}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ UnlockWAL()

Status ROCKSDB_NAMESPACE::DBImpl::UnlockWAL ( )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 1811 번째 라인에서 정의되었습니다.

1811 {
1812 bool signal = false;
1813 uint64_t maybe_stall_begun_count = 0;
1814 uint64_t nonmem_maybe_stall_begun_count = 0;
1815 {
1816 InstrumentedMutexLock lock(&mutex_);
1817 if (lock_wal_count_ == 0) {
1818 return Status::Aborted("No LockWAL() in effect");
1819 }
1821 if (lock_wal_count_ == 0) {
1822 lock_wal_write_token_.reset();
1823 signal = true;
1824 // For the last UnlockWAL, we don't want to return from UnlockWAL()
1825 // until the thread(s) that called BeginWriteStall() have had a chance to
1826 // call EndWriteStall(), so that no_slowdown writes after UnlockWAL() are
1827 // guaranteed to succeed if there's no other source of stall.
1828 maybe_stall_begun_count = write_thread_.GetBegunCountOfOutstandingStall();
1829 if (two_write_queues_) {
1830 nonmem_maybe_stall_begun_count =
1832 }
1833 }
1834 }
1835 if (signal) {
1836 // SignalAll outside of mutex for efficiency
1837 bg_cv_.SignalAll();
1838 }
1839 // Ensure stalls have cleared
1840 if (maybe_stall_begun_count) {
1841 write_thread_.WaitForStallEndedCount(maybe_stall_begun_count);
1842 }
1843 if (nonmem_maybe_stall_begun_count) {
1844 nonmem_write_thread_.WaitForStallEndedCount(nonmem_maybe_stall_begun_count);
1845 }
1846 return Status::OK();
1847}
void WaitForStallEndedCount(uint64_t stall_count)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ UnorderedWriteMemtable()

Status ROCKSDB_NAMESPACE::DBImpl::UnorderedWriteMemtable ( const WriteOptions & write_options,
WriteBatch * my_batch,
WriteCallback * callback,
uint64_t log_ref,
SequenceNumber seq,
const size_t sub_batch_cnt )
protected

db_impl_write.cc 파일의 1071 번째 라인에서 정의되었습니다.

1075 {
1076 PERF_TIMER_GUARD(write_pre_and_post_process_time);
1077 StopWatch write_sw(immutable_db_options_.clock, stats_, DB_WRITE);
1078
1079 WriteThread::Writer w(write_options, my_batch, callback,
1080 /*user_write_cb=*/nullptr, log_ref,
1081 false /*disable_memtable*/);
1082
1083 if (w.CheckCallback(this) && w.ShouldWriteToMemtable()) {
1084 w.sequence = seq;
1085 size_t total_count = WriteBatchInternal::Count(my_batch);
1087 stats->AddDBStats(InternalStats::kIntStatsNumKeysWritten, total_count);
1088 RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
1089
1090 PERF_TIMER_STOP(write_pre_and_post_process_time);
1091 PERF_TIMER_FOR_WAIT_GUARD(write_memtable_time);
1092
1093 ColumnFamilyMemTablesImpl column_family_memtables(
1094 versions_->GetColumnFamilySet());
1095 w.status = WriteBatchInternal::InsertInto(
1096 &w, w.sequence, &column_family_memtables, &flush_scheduler_,
1097 &trim_history_scheduler_, write_options.ignore_missing_column_families,
1098 0 /*log_number*/, this, true /*concurrent_memtable_writes*/,
1099 seq_per_batch_, sub_batch_cnt, true /*batch_per_txn*/,
1100 write_options.memtable_insert_hint_per_batch);
1101 if (write_options.disableWAL) {
1102 has_unpersisted_data_.store(true, std::memory_order_relaxed);
1103 }
1104
1105 PERF_TIMER_START(write_pre_and_post_process_time);
1106 }
1107
1108 size_t pending_cnt = pending_memtable_writes_.fetch_sub(1) - 1;
1109 if (pending_cnt == 0) {
1110 // switch_cv_ waits until pending_memtable_writes_ = 0. Locking its mutex
1111 // before notify ensures that cv is in waiting state when it is notified
1112 // thus not missing the update to pending_memtable_writes_ even though it is
1113 // not modified under the mutex.
1114 std::lock_guard<std::mutex> lck(switch_mutex_);
1115 switch_cv_.notify_all();
1116 }
1117 WriteStatusCheck(w.status);
1118
1119 if (!w.FinalStatus().ok()) {
1120 return w.FinalStatus();
1121 }
1122 return Status::OK();
1123}
std::atomic< size_t > pending_memtable_writes_
Definition db_impl.h:2904
friend class InternalStats
Definition db_impl.h:1706
std::condition_variable switch_cv_
Definition db_impl.h:2900
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ UnscheduleCompactionCallback()

void ROCKSDB_NAMESPACE::DBImpl::UnscheduleCompactionCallback ( void * arg)
staticprivate

db_impl_compaction_flush.cc 파일의 3123 번째 라인에서 정의되었습니다.

3123 {
3124 CompactionArg* ca_ptr = static_cast<CompactionArg*>(arg);
3125 Env::Priority compaction_pri = ca_ptr->compaction_pri_;
3126 if (Env::Priority::BOTTOM == compaction_pri) {
3127 // Decrement bg_bottom_compaction_scheduled_ if priority is BOTTOM
3128 ca_ptr->db->bg_bottom_compaction_scheduled_--;
3129 } else if (Env::Priority::LOW == compaction_pri) {
3130 // Decrement bg_compaction_scheduled_ if priority is LOW
3131 ca_ptr->db->bg_compaction_scheduled_--;
3132 }
3133 CompactionArg ca = *(ca_ptr);
3134 delete static_cast<CompactionArg*>(arg);
3135 if (ca.prepicked_compaction != nullptr) {
3136 // if it's a manual compaction, set status to ManualCompactionPaused
3137 if (ca.prepicked_compaction->manual_compaction_state) {
3138 ca.prepicked_compaction->manual_compaction_state->done = true;
3139 ca.prepicked_compaction->manual_compaction_state->status =
3140 Status::Incomplete(Status::SubCode::kManualCompactionPaused);
3141 }
3142 if (ca.prepicked_compaction->compaction != nullptr) {
3143 ca.prepicked_compaction->compaction->ReleaseCompactionFiles(
3144 Status::Incomplete(Status::SubCode::kManualCompactionPaused));
3145 delete ca.prepicked_compaction->compaction;
3146 }
3147 delete ca.prepicked_compaction;
3148 }
3149 TEST_SYNC_POINT("DBImpl::UnscheduleCompactionCallback");
3150}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ UnscheduleFlushCallback()

void ROCKSDB_NAMESPACE::DBImpl::UnscheduleFlushCallback ( void * arg)
staticprivate

db_impl_compaction_flush.cc 파일의 3152 번째 라인에서 정의되었습니다.

3152 {
3153 // Decrement bg_flush_scheduled_ in flush callback
3154 static_cast<FlushThreadArg*>(arg)->db_->bg_flush_scheduled_--;
3155 Env::Priority flush_pri = static_cast<FlushThreadArg*>(arg)->thread_pri_;
3156 if (Env::Priority::LOW == flush_pri) {
3157 TEST_SYNC_POINT("DBImpl::UnscheduleLowFlushCallback");
3158 } else if (Env::Priority::HIGH == flush_pri) {
3159 TEST_SYNC_POINT("DBImpl::UnscheduleHighFlushCallback");
3160 }
3161 delete static_cast<FlushThreadArg*>(arg);
3162 TEST_SYNC_POINT("DBImpl::UnscheduleFlushCallback");
3163}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ UntrackDataFiles()

void ROCKSDB_NAMESPACE::DBImpl::UntrackDataFiles ( )
protected

db_impl.cc 파일의 533 번째 라인에서 정의되었습니다.

533 {
534 TrackOrUntrackFiles(/*existing_data_files=*/{},
535 /*track=*/false);
536}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ UpdateDeletionCompactionStats()

void ROCKSDB_NAMESPACE::DBImpl::UpdateDeletionCompactionStats ( const std::unique_ptr< Compaction > & c)
private

db_impl_compaction_flush.cc 파일의 4184 번째 라인에서 정의되었습니다.

4185 {
4186 if (c == nullptr) {
4187 return;
4188 }
4189
4190 CompactionReason reason = c->compaction_reason();
4191
4192 switch (reason) {
4193 case CompactionReason::kFIFOMaxSize:
4194 RecordTick(stats_, FIFO_MAX_SIZE_COMPACTIONS);
4195 break;
4196 case CompactionReason::kFIFOTtl:
4197 RecordTick(stats_, FIFO_TTL_COMPACTIONS);
4198 break;
4199 default:
4200 assert(false);
4201 break;
4202 }
4203}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ValidateOptions() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::ValidateOptions ( const DBOptions & db_options)
staticprivate

db_impl_open.cc 파일의 232 번째 라인에서 정의되었습니다.

232 {
233 if (db_options.db_paths.size() > 4) {
234 return Status::NotSupported(
235 "More than four DB paths are not supported yet. ");
236 }
237
238 if (db_options.allow_mmap_reads && db_options.use_direct_reads) {
239 // Protect against assert in PosixMMapReadableFile constructor
240 return Status::NotSupported(
241 "If memory mapped reads (allow_mmap_reads) are enabled "
242 "then direct I/O reads (use_direct_reads) must be disabled. ");
243 }
244
245 if (db_options.allow_mmap_writes &&
246 db_options.use_direct_io_for_flush_and_compaction) {
247 return Status::NotSupported(
248 "If memory mapped writes (allow_mmap_writes) are enabled "
249 "then direct I/O writes (use_direct_io_for_flush_and_compaction) must "
250 "be disabled. ");
251 }
252
253 if (db_options.keep_log_file_num == 0) {
254 return Status::InvalidArgument("keep_log_file_num must be greater than 0");
255 }
256
257 if (db_options.unordered_write &&
258 !db_options.allow_concurrent_memtable_write) {
259 return Status::InvalidArgument(
260 "unordered_write is incompatible with "
261 "!allow_concurrent_memtable_write");
262 }
263
264 if (db_options.unordered_write && db_options.enable_pipelined_write) {
265 return Status::InvalidArgument(
266 "unordered_write is incompatible with enable_pipelined_write");
267 }
268
269 if (db_options.atomic_flush && db_options.enable_pipelined_write) {
270 return Status::InvalidArgument(
271 "atomic_flush is incompatible with enable_pipelined_write");
272 }
273
274 if (db_options.use_direct_io_for_flush_and_compaction &&
275 0 == db_options.writable_file_max_buffer_size) {
276 return Status::InvalidArgument(
277 "writes in direct IO require writable_file_max_buffer_size > 0");
278 }
279
280 if (db_options.daily_offpeak_time_utc != "") {
281 int start_time, end_time;
282 if (!TryParseTimeRangeString(db_options.daily_offpeak_time_utc, start_time,
283 end_time)) {
284 return Status::InvalidArgument(
285 "daily_offpeak_time_utc should be set in the format HH:mm-HH:mm "
286 "(e.g. 04:30-07:30)");
287 } else if (start_time == end_time) {
288 return Status::InvalidArgument(
289 "start_time and end_time cannot be the same");
290 }
291 }
292
293 if (!db_options.write_dbid_to_manifest && !db_options.write_identity_file) {
294 return Status::InvalidArgument(
295 "write_dbid_to_manifest and write_identity_file cannot both be false");
296 }
297 return Status::OK();
298}
bool TryParseTimeRangeString(const std::string &value, int &start_time, int &end_time)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ValidateOptions() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::ValidateOptions ( const DBOptions & db_options,
const std::vector< ColumnFamilyDescriptor > & column_families )
staticprivate

db_impl_open.cc 파일의 218 번째 라인에서 정의되었습니다.

220 {
221 Status s;
222 for (auto& cfd : column_families) {
223 s = ColumnFamilyData::ValidateOptions(db_options, cfd.options);
224 if (!s.ok()) {
225 return s;
226 }
227 }
228 s = ValidateOptions(db_options);
229 return s;
230}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ VerifyChecksum() [1/2]

virtual Status ROCKSDB_NAMESPACE::DB::VerifyChecksum ( )
inlinevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db.h 파일의 1990 번째 라인에서 정의되었습니다.

1990{ return VerifyChecksum(ReadOptions()); }
Status VerifyChecksum(const ReadOptions &) override
Definition db_impl.cc:6476

◆ VerifyChecksum() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::VerifyChecksum ( const ReadOptions & _read_options)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl.cc 파일의 6476 번째 라인에서 정의되었습니다.

6476 {
6477 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
6478 _read_options.io_activity != Env::IOActivity::kVerifyDBChecksum) {
6479 return Status::InvalidArgument(
6480 "Can only call VerifyChecksum with `ReadOptions::io_activity` is "
6481 "`Env::IOActivity::kUnknown` or `Env::IOActivity::kVerifyDBChecksum`");
6482 }
6483 ReadOptions read_options(_read_options);
6484 if (read_options.io_activity == Env::IOActivity::kUnknown) {
6485 read_options.io_activity = Env::IOActivity::kVerifyDBChecksum;
6486 }
6487 return VerifyChecksumInternal(read_options,
6488 /*use_file_checksum=*/false);
6489}
Status VerifyChecksumInternal(const ReadOptions &read_options, bool use_file_checksum)
Definition db_impl.cc:6491
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ VerifyChecksumInternal()

Status ROCKSDB_NAMESPACE::DBImpl::VerifyChecksumInternal ( const ReadOptions & read_options,
bool use_file_checksum )

db_impl.cc 파일의 6491 번째 라인에서 정의되었습니다.

6492 {
6493 // `bytes_read` stat is enabled based on compile-time support and cannot
6494 // be dynamically toggled. So we do not need to worry about `PerfLevel`
6495 // here, unlike many other `IOStatsContext` / `PerfContext` stats.
6496 uint64_t prev_bytes_read = IOSTATS(bytes_read);
6497
6498 Status s;
6499
6500 if (use_file_checksum) {
6501 FileChecksumGenFactory* const file_checksum_gen_factory =
6503 if (!file_checksum_gen_factory) {
6504 s = Status::InvalidArgument(
6505 "Cannot verify file checksum if options.file_checksum_gen_factory is "
6506 "null");
6507 return s;
6508 }
6509 }
6510 // FIXME? What does it mean if read_options.verify_checksums == false?
6511
6512 // TODO: simplify using GetRefedColumnFamilySet?
6513 std::vector<ColumnFamilyData*> cfd_list;
6514 {
6515 InstrumentedMutexLock l(&mutex_);
6516 for (auto cfd : *versions_->GetColumnFamilySet()) {
6517 if (!cfd->IsDropped() && cfd->initialized()) {
6518 cfd->Ref();
6519 cfd_list.push_back(cfd);
6520 }
6521 }
6522 }
6523 std::vector<SuperVersion*> sv_list;
6524 for (auto cfd : cfd_list) {
6525 sv_list.push_back(cfd->GetReferencedSuperVersion(this));
6526 }
6527
6528 for (auto& sv : sv_list) {
6529 VersionStorageInfo* vstorage = sv->current->storage_info();
6530 ColumnFamilyData* cfd = sv->current->cfd();
6531 Options opts;
6532 if (!use_file_checksum) {
6533 InstrumentedMutexLock l(&mutex_);
6534 opts = Options(BuildDBOptions(immutable_db_options_, mutable_db_options_),
6535 cfd->GetLatestCFOptions());
6536 }
6537 for (int i = 0; i < vstorage->num_non_empty_levels() && s.ok(); i++) {
6538 for (size_t j = 0; j < vstorage->LevelFilesBrief(i).num_files && s.ok();
6539 j++) {
6540 const auto& fd_with_krange = vstorage->LevelFilesBrief(i).files[j];
6541 const auto& fd = fd_with_krange.fd;
6542 const FileMetaData* fmeta = fd_with_krange.file_metadata;
6543 assert(fmeta);
6544 std::string fname = TableFileName(cfd->ioptions()->cf_paths,
6545 fd.GetNumber(), fd.GetPathId());
6546 if (use_file_checksum) {
6547 s = VerifyFullFileChecksum(fmeta->file_checksum,
6548 fmeta->file_checksum_func_name, fname,
6549 read_options);
6550 } else {
6552 opts, file_options_, read_options, fname, fd.largest_seqno);
6553 }
6554 RecordTick(stats_, VERIFY_CHECKSUM_READ_BYTES,
6555 IOSTATS(bytes_read) - prev_bytes_read);
6556 prev_bytes_read = IOSTATS(bytes_read);
6557 }
6558 }
6559
6560 if (s.ok() && use_file_checksum) {
6561 const auto& blob_files = vstorage->GetBlobFiles();
6562 for (const auto& meta : blob_files) {
6563 assert(meta);
6564
6565 const uint64_t blob_file_number = meta->GetBlobFileNumber();
6566
6567 const std::string blob_file_name = BlobFileName(
6568 cfd->ioptions()->cf_paths.front().path, blob_file_number);
6569 s = VerifyFullFileChecksum(meta->GetChecksumValue(),
6570 meta->GetChecksumMethod(), blob_file_name,
6571 read_options);
6572 RecordTick(stats_, VERIFY_CHECKSUM_READ_BYTES,
6573 IOSTATS(bytes_read) - prev_bytes_read);
6574 prev_bytes_read = IOSTATS(bytes_read);
6575 if (!s.ok()) {
6576 break;
6577 }
6578 }
6579 }
6580 if (!s.ok()) {
6581 break;
6582 }
6583 }
6584
6586 {
6587 InstrumentedMutexLock l(&mutex_);
6588 for (auto sv : sv_list) {
6589 if (sv && sv->Unref()) {
6590 sv->Cleanup();
6591 if (defer_purge) {
6593 } else {
6594 delete sv;
6595 }
6596 }
6597 }
6598 if (defer_purge) {
6599 SchedulePurge();
6600 }
6601 for (auto cfd : cfd_list) {
6602 cfd->UnrefAndTryDelete();
6603 }
6604 }
6605 RecordTick(stats_, VERIFY_CHECKSUM_READ_BYTES,
6606 IOSTATS(bytes_read) - prev_bytes_read);
6607 return s;
6608}
Status VerifyFullFileChecksum(const std::string &file_checksum_expected, const std::string &func_name_expected, const std::string &fpath, const ReadOptions &read_options)
Definition db_impl.cc:6610
#define IOSTATS(metric)
Status VerifySstFileChecksumInternal(const Options &options, const EnvOptions &env_options, const ReadOptions &read_options, const std::string &file_path, const SequenceNumber &largest_seqno)
std::shared_ptr< FileChecksumGenFactory > file_checksum_gen_factory
Definition db_options.h:95
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ VerifyFileChecksums()

Status ROCKSDB_NAMESPACE::DBImpl::VerifyFileChecksums ( const ReadOptions & read_options)
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl.cc 파일의 6460 번째 라인에서 정의되었습니다.

6460 {
6461 if (_read_options.io_activity != Env::IOActivity::kUnknown &&
6462 _read_options.io_activity != Env::IOActivity::kVerifyFileChecksums) {
6463 return Status::InvalidArgument(
6464 "Can only call VerifyFileChecksums with `ReadOptions::io_activity` is "
6465 "`Env::IOActivity::kUnknown` or "
6466 "`Env::IOActivity::kVerifyFileChecksums`");
6467 }
6468 ReadOptions read_options(_read_options);
6469 if (read_options.io_activity == Env::IOActivity::kUnknown) {
6470 read_options.io_activity = Env::IOActivity::kVerifyFileChecksums;
6471 }
6472 return VerifyChecksumInternal(read_options,
6473 /*use_file_checksum=*/true);
6474}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ VerifyFullFileChecksum()

Status ROCKSDB_NAMESPACE::DBImpl::VerifyFullFileChecksum ( const std::string & file_checksum_expected,
const std::string & func_name_expected,
const std::string & fpath,
const ReadOptions & read_options )

db_impl.cc 파일의 6610 번째 라인에서 정의되었습니다.

6613 {
6614 Status s;
6615 if (file_checksum_expected == kUnknownFileChecksum) {
6616 return s;
6617 }
6618 std::string file_checksum;
6619 std::string func_name;
6622 func_name_expected, &file_checksum, &func_name,
6623 read_options.readahead_size, immutable_db_options_.allow_mmap_reads,
6624 io_tracer_, immutable_db_options_.rate_limiter.get(), read_options,
6626 if (s.ok()) {
6627 assert(func_name_expected == func_name);
6628 if (file_checksum != file_checksum_expected) {
6629 std::ostringstream oss;
6630 oss << fname << " file checksum mismatch, ";
6631 oss << "expecting "
6632 << Slice(file_checksum_expected).ToString(/*hex=*/true);
6633 oss << ", but actual " << Slice(file_checksum).ToString(/*hex=*/true);
6634 s = Status::Corruption(oss.str());
6635 TEST_SYNC_POINT_CALLBACK("DBImpl::VerifyFullFileChecksum:mismatch", &s);
6636 }
6637 }
6638 return s;
6639}
IOStatus GenerateOneFileChecksum(FileSystem *fs, const std::string &file_path, FileChecksumGenFactory *checksum_factory, const std::string &requested_checksum_func_name, std::string *file_checksum, std::string *file_checksum_func_name, size_t verify_checksums_readahead_size, bool, std::shared_ptr< IOTracer > &io_tracer, RateLimiter *rate_limiter, const ReadOptions &read_options, Statistics *stats, SystemClock *clock)
Definition file_util.cc:157
std::shared_ptr< RateLimiter > rate_limiter
Definition db_options.h:32
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WaitForBackgroundWork()

void ROCKSDB_NAMESPACE::DBImpl::WaitForBackgroundWork ( )
private

db_impl.cc 파일의 489 번째 라인에서 정의되었습니다.

489 {
490 // Wait for background work to finish
491 while (bg_bottom_compaction_scheduled_ || bg_compaction_scheduled_ ||
492 bg_flush_scheduled_) {
493 bg_cv_.Wait();
494 }
495}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WaitForCompact()

Status ROCKSDB_NAMESPACE::DBImpl::WaitForCompact ( const WaitForCompactOptions & wait_for_compact_options)
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

db_impl_compaction_flush.cc 파일의 4389 번째 라인에서 정의되었습니다.

4390 {
4391 InstrumentedMutexLock l(&mutex_);
4392 if (wait_for_compact_options.flush) {
4393 Status s = DBImpl::FlushAllColumnFamilies(FlushOptions(),
4394 FlushReason::kManualFlush);
4395 if (!s.ok()) {
4396 return s;
4397 }
4398 } else if (wait_for_compact_options.close_db &&
4399 has_unpersisted_data_.load(std::memory_order_relaxed) &&
4401 Status s =
4402 DBImpl::FlushAllColumnFamilies(FlushOptions(), FlushReason::kShutDown);
4403 if (!s.ok()) {
4404 return s;
4405 }
4406 }
4407 TEST_SYNC_POINT("DBImpl::WaitForCompact:StartWaiting");
4408 const auto deadline = immutable_db_options_.clock->NowMicros() +
4409 wait_for_compact_options.timeout.count();
4410 for (;;) {
4411 if (shutting_down_.load(std::memory_order_acquire)) {
4412 return Status::ShutdownInProgress();
4413 }
4414 if (bg_work_paused_ && wait_for_compact_options.abort_on_pause) {
4415 return Status::Aborted();
4416 }
4417 if ((bg_bottom_compaction_scheduled_ || bg_compaction_scheduled_ ||
4418 bg_flush_scheduled_ || unscheduled_compactions_ ||
4419 (wait_for_compact_options.wait_for_purge && bg_purge_scheduled_) ||
4420 unscheduled_flushes_ || error_handler_.IsRecoveryInProgress()) &&
4422 if (wait_for_compact_options.timeout.count()) {
4423 if (bg_cv_.TimedWait(deadline)) {
4424 return Status::TimedOut();
4425 }
4426 } else {
4427 TEST_SYNC_POINT("DBImpl::WaitForCompact:InsideLoop");
4428 bg_cv_.Wait();
4429 }
4430 } else if (wait_for_compact_options.close_db) {
4432 mutex_.Unlock();
4433 Status s = Close();
4434 mutex_.Lock();
4435 if (!s.ok()) {
4437 }
4438 return s;
4439 } else {
4440 return error_handler_.GetBGError();
4441 }
4442 }
4443}
Status Close() override
Definition db_impl.cc:5321
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WaitForFlushMemTable()

Status ROCKSDB_NAMESPACE::DBImpl::WaitForFlushMemTable ( ColumnFamilyData * cfd,
const uint64_t * flush_memtable_id = nullptr,
bool resuming_from_bg_err = false,
std::optional< FlushReason > flush_reason = std::nullopt )
inlineprivate

db_impl.h 파일의 2137 번째 라인에서 정의되었습니다.

2140 {
2141 return WaitForFlushMemTables({cfd}, {flush_memtable_id},
2142 resuming_from_bg_err, flush_reason);
2143 }
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WaitForFlushMemTables()

Status ROCKSDB_NAMESPACE::DBImpl::WaitForFlushMemTables ( const autovector< ColumnFamilyData * > & cfds,
const autovector< const uint64_t * > & flush_memtable_ids,
bool resuming_from_bg_err,
std::optional< FlushReason > flush_reason )
private

db_impl_compaction_flush.cc 파일의 2720 번째 라인에서 정의되었습니다.

2723 {
2724 int num = static_cast<int>(cfds.size());
2725 // Wait until the compaction completes
2726 InstrumentedMutexLock l(&mutex_);
2727 Status s;
2728 // If the caller is trying to resume from bg error, then
2729 // error_handler_.IsDBStopped() is true.
2730 while (resuming_from_bg_err || !error_handler_.IsDBStopped()) {
2731 if (shutting_down_.load(std::memory_order_acquire)) {
2732 s = Status::ShutdownInProgress();
2733 return s;
2734 }
2735 // If an error has occurred during resumption, then no need to wait.
2736 // But flush operation may fail because of this error, so need to
2737 // return the status.
2740 break;
2741 }
2742 // If BGWorkStopped, which indicate that there is a BG error and
2743 // 1) soft error but requires no BG work, 2) no in auto_recovery_
2744 if (!resuming_from_bg_err && error_handler_.IsBGWorkStopped() &&
2745 error_handler_.GetBGError().severity() < Status::Severity::kHardError) {
2747 return s;
2748 }
2749
2750 // Number of column families that have been dropped.
2751 int num_dropped = 0;
2752 // Number of column families that have finished flush.
2753 int num_finished = 0;
2754 for (int i = 0; i < num; ++i) {
2755 if (cfds[i]->IsDropped()) {
2756 ++num_dropped;
2757 } else if (cfds[i]->imm()->NumNotFlushed() == 0 ||
2758 (flush_memtable_ids[i] != nullptr &&
2759 cfds[i]->imm()->GetEarliestMemTableID() >
2760 *flush_memtable_ids[i])) {
2761 // Make file ingestion's flush wait until SuperVersion is also updated
2762 // since after flush, it does range overlapping check and file level
2763 // assignment with the current SuperVersion.
2764 if (!flush_reason.has_value() ||
2765 flush_reason.value() != FlushReason::kExternalFileIngestion ||
2766 cfds[i]->GetSuperVersion()->imm->GetID() ==
2767 cfds[i]->imm()->current()->GetID()) {
2768 ++num_finished;
2769 }
2770 }
2771 }
2772 if (1 == num_dropped && 1 == num) {
2773 s = Status::ColumnFamilyDropped();
2774 return s;
2775 }
2776 // Column families involved in this flush request have either been dropped
2777 // or finished flush. Then it's time to finish waiting.
2778 if (num_dropped + num_finished == num) {
2779 break;
2780 }
2781 bg_cv_.Wait();
2782 }
2783 // If not resuming from bg error, and an error has caused the DB to stop,
2784 // then report the bg error to caller.
2785 if (!resuming_from_bg_err && error_handler_.IsDBStopped()) {
2787 }
2788 return s;
2789}
Severity severity() const
Definition status.h:143
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WaitForPendingWrites()

void ROCKSDB_NAMESPACE::DBImpl::WaitForPendingWrites ( )
inlineprivate

db_impl.h 파일의 2150 번째 라인에서 정의되었습니다.

2150 {
2151 mutex_.AssertHeld();
2152 TEST_SYNC_POINT("DBImpl::WaitForPendingWrites:BeforeBlock");
2153 // In case of pipelined write is enabled, wait for all pending memtable
2154 // writers.
2156 // Memtable writers may call DB::Get in case max_successive_merges > 0,
2157 // which may lock mutex. Unlocking mutex here to avoid deadlock.
2158 mutex_.Unlock();
2160 mutex_.Lock();
2161 }
2162
2164 // Wait for the ones who already wrote to the WAL to finish their
2165 // memtable write.
2166 if (pending_memtable_writes_.load() != 0) {
2167 // XXX: suspicious wait while holding DB mutex?
2168 std::unique_lock<std::mutex> guard(switch_mutex_);
2169 switch_cv_.wait(guard,
2170 [&] { return pending_memtable_writes_.load() == 0; });
2171 }
2172 } else {
2173 // (Writes are finished before the next write group starts.)
2174 }
2175
2176 // Wait for any LockWAL to clear
2177 while (lock_wal_count_ > 0) {
2178 bg_cv_.Wait();
2179 }
2180 }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WaitUntilFlushWouldNotStallWrites()

Status ROCKSDB_NAMESPACE::DBImpl::WaitUntilFlushWouldNotStallWrites ( ColumnFamilyData * cfd,
bool * flush_needed )
private

db_impl_compaction_flush.cc 파일의 2639 번째 라인에서 정의되었습니다.

2640 {
2641 {
2642 *flush_needed = true;
2643 InstrumentedMutexLock l(&mutex_);
2644 uint64_t orig_active_memtable_id = cfd->mem()->GetID();
2645 WriteStallCondition write_stall_condition = WriteStallCondition::kNormal;
2646 do {
2647 if (write_stall_condition != WriteStallCondition::kNormal) {
2648 // Same error handling as user writes: Don't wait if there's a
2649 // background error, even if it's a soft error. We might wait here
2650 // indefinitely as the pending flushes/compactions may never finish
2651 // successfully, resulting in the stall condition lasting indefinitely
2653 return error_handler_.GetBGError();
2654 }
2655
2656 TEST_SYNC_POINT("DBImpl::WaitUntilFlushWouldNotStallWrites:StallWait");
2658 "[%s] WaitUntilFlushWouldNotStallWrites"
2659 " waiting on stall conditions to clear",
2660 cfd->GetName().c_str());
2661 bg_cv_.Wait();
2662 }
2663 if (cfd->IsDropped()) {
2664 return Status::ColumnFamilyDropped();
2665 }
2666 if (shutting_down_.load(std::memory_order_acquire)) {
2667 return Status::ShutdownInProgress();
2668 }
2669
2670 uint64_t earliest_memtable_id =
2671 std::min(cfd->mem()->GetID(), cfd->imm()->GetEarliestMemTableID());
2672 if (earliest_memtable_id > orig_active_memtable_id) {
2673 // We waited so long that the memtable we were originally waiting on was
2674 // flushed.
2675 *flush_needed = false;
2676 return Status::OK();
2677 }
2678
2679 const auto& mutable_cf_options = *cfd->GetLatestMutableCFOptions();
2680 const auto* vstorage = cfd->current()->storage_info();
2681
2682 // Skip stalling check if we're below auto-flush and auto-compaction
2683 // triggers. If it stalled in these conditions, that'd mean the stall
2684 // triggers are so low that stalling is needed for any background work. In
2685 // that case we shouldn't wait since background work won't be scheduled.
2686 if (cfd->imm()->NumNotFlushed() <
2687 cfd->ioptions()->min_write_buffer_number_to_merge &&
2688 vstorage->l0_delay_trigger_count() <
2689 mutable_cf_options.level0_file_num_compaction_trigger) {
2690 break;
2691 }
2692
2693 // check whether one extra immutable memtable or an extra L0 file would
2694 // cause write stalling mode to be entered. It could still enter stall
2695 // mode due to pending compaction bytes, but that's less common
2696 // No extra immutable Memtable will be created if the current Memtable is
2697 // empty.
2698 write_stall_condition =
2699 ColumnFamilyData::GetWriteStallConditionAndCause(
2700 cfd->GetUnflushedMemTableCountForWriteStallCheck(),
2701 vstorage->l0_delay_trigger_count() + 1,
2702 vstorage->estimated_compaction_needed_bytes(), mutable_cf_options,
2703 *cfd->ioptions())
2704 .first;
2705 } while (write_stall_condition != WriteStallCondition::kNormal);
2706 }
2707 return Status::OK();
2708}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WALBufferIsEmpty()

bool ROCKSDB_NAMESPACE::DBImpl::WALBufferIsEmpty ( )

db_impl.cc 파일의 1578 번째 라인에서 정의되었습니다.

1578 {
1579 InstrumentedMutexLock l(&log_write_mutex_);
1580 log::Writer* cur_log_writer = logs_.back().writer;
1581 auto res = cur_log_writer->BufferIsEmpty();
1582 return res;
1583}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WALIOStatusCheck()

void ROCKSDB_NAMESPACE::DBImpl::WALIOStatusCheck ( const IOStatus & status)
private

db_impl_write.cc 파일의 1366 번째 라인에서 정의되었습니다.

1366 {
1367 // Is setting bg_error_ enough here? This will at least stop
1368 // compaction and fail any further writes.
1369 if ((immutable_db_options_.paranoid_checks && !io_status.ok() &&
1370 !io_status.IsBusy() && !io_status.IsIncomplete()) ||
1371 io_status.IsIOFenced()) {
1372 mutex_.Lock();
1373 // Maybe change the return status to void?
1374 error_handler_.SetBGError(io_status, BackgroundErrorReason::kWriteCallback,
1375 /*wal_related=*/true);
1376 mutex_.Unlock();
1377 } else {
1378 // Force writable file to be continue writable.
1379 logs_.back().writer->file()->reset_seen_error();
1380 }
1381}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WrapUpCreateColumnFamilies()

Status ROCKSDB_NAMESPACE::DBImpl::WrapUpCreateColumnFamilies ( const ReadOptions & read_options,
const WriteOptions & write_options,
const std::vector< const ColumnFamilyOptions * > & cf_options )
private

db_impl.cc 파일의 3499 번째 라인에서 정의되었습니다.

3501 {
3503
3504 // NOTE: this function is skipped for create_missing_column_families and
3505 // DB::Open, so new functionality here might need to go into Open also.
3506 bool register_worker = false;
3507 for (auto* opts_ptr : cf_options) {
3508 if (opts_ptr->preserve_internal_time_seconds > 0 ||
3509 opts_ptr->preclude_last_level_data_seconds > 0) {
3510 register_worker = true;
3511 break;
3512 }
3513 }
3514 // Attempt both follow-up actions even if one fails
3515 Status s = WriteOptionsFile(write_options, false /*db_mutex_already_held*/);
3516 if (register_worker) {
3517 s.UpdateIfOk(RegisterRecordSeqnoTimeWorker(read_options, write_options,
3518 /* is_new_db */ false));
3519 }
3520 return s;
3521}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Write()

Status ROCKSDB_NAMESPACE::DBImpl::Write ( const WriteOptions & options,
WriteBatch * updates )
overridevirtual

ROCKSDB_NAMESPACE::DB를 구현.

ROCKSDB_NAMESPACE::DBImplReadOnly, ROCKSDB_NAMESPACE::DBImplSecondary에서 재구현되었습니다.

db_impl_write.cc 파일의 151 번째 라인에서 정의되었습니다.

151 {
152 Status s;
153 if (write_options.protection_bytes_per_key > 0) {
154 s = WriteBatchInternal::UpdateProtectionInfo(
155 my_batch, write_options.protection_bytes_per_key);
156 }
157 if (s.ok()) {
158 s = WriteImpl(write_options, my_batch, /*callback=*/nullptr,
159 /*user_write_cb=*/nullptr,
160 /*log_used=*/nullptr);
161 }
162 return s;
163}
Status WriteImpl(const WriteOptions &options, WriteBatch *updates, WriteCallback *callback=nullptr, UserWriteCallback *user_write_cb=nullptr, uint64_t *log_used=nullptr, uint64_t log_ref=0, bool disable_memtable=false, uint64_t *seq_used=nullptr, size_t batch_cnt=0, PreReleaseCallback *pre_release_callback=nullptr, PostMemTableCallback *post_memtable_callback=nullptr, std::shared_ptr< WriteBatchWithIndex > wbwi=nullptr, uint64_t min_prep_log=0)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ write_controller()

const WriteController & ROCKSDB_NAMESPACE::DBImpl::write_controller ( )
inline

db_impl.h 파일의 949 번째 라인에서 정의되었습니다.

949{ return write_controller_; }
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteBufferManagerStallWrites()

void ROCKSDB_NAMESPACE::DBImpl::WriteBufferManagerStallWrites ( )
private

db_impl_write.cc 파일의 2202 번째 라인에서 정의되었습니다.

2202 {
2203 mutex_.AssertHeld();
2204 // First block future writer threads who want to add themselves to the queue
2205 // of WriteThread.
2207 mutex_.Unlock();
2208
2209 // Change the state to State::Blocked.
2210 static_cast<WBMStallInterface*>(wbm_stall_.get())
2211 ->SetState(WBMStallInterface::State::BLOCKED);
2212 // Then WriteBufferManager will add DB instance to its queue
2213 // and block this thread by calling WBMStallInterface::Block().
2215 wbm_stall_->Block();
2216
2217 mutex_.Lock();
2218 // Stall has ended. Signal writer threads so that they can add
2219 // themselves to the WriteThread queue for writes.
2221}
void BeginWriteStall(StallInterface *wbm_stall)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteImpl()

Status ROCKSDB_NAMESPACE::DBImpl::WriteImpl ( const WriteOptions & options,
WriteBatch * updates,
WriteCallback * callback = nullptr,
UserWriteCallback * user_write_cb = nullptr,
uint64_t * log_used = nullptr,
uint64_t log_ref = 0,
bool disable_memtable = false,
uint64_t * seq_used = nullptr,
size_t batch_cnt = 0,
PreReleaseCallback * pre_release_callback = nullptr,
PostMemTableCallback * post_memtable_callback = nullptr,
std::shared_ptr< WriteBatchWithIndex > wbwi = nullptr,
uint64_t min_prep_log = 0 )
protected

db_impl_write.cc 파일의 315 번째 라인에서 정의되었습니다.

323 {
324 assert(!seq_per_batch_ || batch_cnt != 0);
325 assert(my_batch == nullptr || my_batch->Count() == 0 ||
326 write_options.protection_bytes_per_key == 0 ||
327 write_options.protection_bytes_per_key ==
328 my_batch->GetProtectionBytesPerKey());
329 if (my_batch == nullptr) {
330 return Status::InvalidArgument("Batch is nullptr!");
331 } else if (!disable_memtable &&
332 WriteBatchInternal::TimestampsUpdateNeeded(*my_batch)) {
333 // If writing to memtable, then we require the caller to set/update the
334 // timestamps for the keys in the write batch.
335 // Otherwise, it means we are just writing to the WAL, and we allow
336 // timestamps unset for the keys in the write batch. This can happen if we
337 // use TransactionDB with write-committed policy, and we currently do not
338 // support user-defined timestamp with other policies.
339 // In the prepare phase, a transaction can write the batch to the WAL
340 // without inserting to memtable. The keys in the batch do not have to be
341 // assigned timestamps because they will be used only during recovery if
342 // there is a commit marker which includes their commit timestamp.
343 return Status::InvalidArgument("write batch must have timestamp(s) set");
344 } else if (write_options.rate_limiter_priority != Env::IO_TOTAL &&
345 write_options.rate_limiter_priority != Env::IO_USER) {
346 return Status::InvalidArgument(
347 "WriteOptions::rate_limiter_priority only allows "
348 "Env::IO_TOTAL and Env::IO_USER due to implementation constraints");
349 } else if (write_options.rate_limiter_priority != Env::IO_TOTAL &&
350 (write_options.disableWAL || manual_wal_flush_)) {
351 return Status::InvalidArgument(
352 "WriteOptions::rate_limiter_priority currently only supports "
353 "rate-limiting automatic WAL flush, which requires "
354 "`WriteOptions::disableWAL` and "
355 "`DBOptions::manual_wal_flush` both set to false");
356 } else if (write_options.protection_bytes_per_key != 0 &&
357 write_options.protection_bytes_per_key != 8) {
358 return Status::InvalidArgument(
359 "`WriteOptions::protection_bytes_per_key` must be zero or eight");
360 } else if (write_options.disableWAL &&
362 !(two_write_queues_ && disable_memtable)) {
363 // Corruption detection in recycled WALs relies on sequential sequence
364 // numbers, but WritePreparedTxnDB uses disableWAL internally for split
365 // writes
366 return Status::InvalidArgument(
367 "WriteOptions::disableWAL option is not supported if "
368 "DBOptions::recycle_log_file_num > 0");
369 }
370 // TODO: this use of operator bool on `tracer_` can avoid unnecessary lock
371 // grabs but does not seem thread-safe.
372 if (tracer_) {
373 InstrumentedMutexLock lock(&trace_mutex_);
374 if (tracer_ && !tracer_->IsWriteOrderPreserved()) {
375 // We don't have to preserve write order so can trace anywhere. It's more
376 // efficient to trace here than to add latency to a phase of the log/apply
377 // pipeline.
378 // TODO: maybe handle the tracing status?
379 tracer_->Write(my_batch).PermitUncheckedError();
380 }
381 }
382 if (write_options.sync && write_options.disableWAL) {
383 return Status::InvalidArgument("Sync writes has to enable WAL.");
384 }
385 if (two_write_queues_ && immutable_db_options_.enable_pipelined_write) {
386 return Status::NotSupported(
387 "pipelined_writes is not compatible with concurrent prepares");
388 }
389 if (seq_per_batch_ && immutable_db_options_.enable_pipelined_write) {
390 // TODO(yiwu): update pipeline write with seq_per_batch and batch_cnt
391 return Status::NotSupported(
392 "pipelined_writes is not compatible with seq_per_batch");
393 }
396 return Status::NotSupported(
397 "pipelined_writes is not compatible with unordered_write");
398 }
400 post_memtable_callback != nullptr) {
401 return Status::NotSupported(
402 "pipelined write currently does not honor post_memtable_callback");
403 }
404 if (seq_per_batch_ && post_memtable_callback != nullptr) {
405 return Status::NotSupported(
406 "seq_per_batch currently does not honor post_memtable_callback");
407 }
408 if (my_batch->HasDeleteRange() && immutable_db_options_.row_cache) {
409 return Status::NotSupported(
410 "DeleteRange is not compatible with row cache.");
411 }
412 if (wbwi) {
413 assert(prep_log > 0);
414 // Used only in WriteCommittedTxn::CommitInternal() with no `callback`.
415 assert(!callback);
417 return Status::NotSupported(
418 "Ingesting WriteBatch does not support unordered_write");
419 }
421 return Status::NotSupported(
422 "Ingesting WriteBatch does not support pipelined_write");
423 }
425 return Status::NotSupported(
426 "Ingesting WriteBatch does not support atomic_flush");
427 }
428 }
429 // Otherwise IsLatestPersistentState optimization does not make sense
430 assert(!WriteBatchInternal::IsLatestPersistentState(my_batch) ||
431 disable_memtable);
432
433 if (write_options.low_pri) {
434 Status s = ThrottleLowPriWritesIfNeeded(write_options, my_batch);
435 if (!s.ok()) {
436 return s;
437 }
438 }
439
440 if (two_write_queues_ && disable_memtable) {
441 AssignOrder assign_order =
443 // Otherwise it is WAL-only Prepare batches in WriteCommitted policy and
444 // they don't consume sequence.
445 return WriteImplWALOnly(
446 &nonmem_write_thread_, write_options, my_batch, callback, user_write_cb,
447 log_used, log_ref, seq_used, batch_cnt, pre_release_callback,
448 assign_order, kDontPublishLastSeq, disable_memtable);
449 }
450
452 const size_t sub_batch_cnt = batch_cnt != 0
453 ? batch_cnt
454 // every key is a sub-batch consuming a seq
455 : WriteBatchInternal::Count(my_batch);
456 uint64_t seq = 0;
457 // Use a write thread to i) optimize for WAL write, ii) publish last
458 // sequence in in increasing order, iii) call pre_release_callback serially
459 Status status = WriteImplWALOnly(
460 &write_thread_, write_options, my_batch, callback, user_write_cb,
461 log_used, log_ref, &seq, sub_batch_cnt, pre_release_callback,
462 kDoAssignOrder, kDoPublishLastSeq, disable_memtable);
463 TEST_SYNC_POINT("DBImpl::WriteImpl:UnorderedWriteAfterWriteWAL");
464 if (!status.ok()) {
465 return status;
466 }
467 if (seq_used) {
468 *seq_used = seq;
469 }
470 if (!disable_memtable) {
471 TEST_SYNC_POINT("DBImpl::WriteImpl:BeforeUnorderedWriteMemtable");
472 status = UnorderedWriteMemtable(write_options, my_batch, callback,
473 log_ref, seq, sub_batch_cnt);
474 }
475 return status;
476 }
477
479 return PipelinedWriteImpl(write_options, my_batch, callback, user_write_cb,
480 log_used, log_ref, disable_memtable, seq_used);
481 }
482
483 PERF_TIMER_GUARD(write_pre_and_post_process_time);
484 WriteThread::Writer w(write_options, my_batch, callback, user_write_cb,
485 log_ref, disable_memtable, batch_cnt,
486 pre_release_callback, post_memtable_callback,
487 /*_ingest_wbwi=*/wbwi != nullptr);
488 StopWatch write_sw(immutable_db_options_.clock, stats_, DB_WRITE);
489
491 if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_CALLER) {
493 }
494 if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
495 // we are a non-leader in a parallel group
496
497 if (w.ShouldWriteToMemtable()) {
498 PERF_TIMER_STOP(write_pre_and_post_process_time);
499 PERF_TIMER_FOR_WAIT_GUARD(write_memtable_time);
500
501 ColumnFamilyMemTablesImpl column_family_memtables(
502 versions_->GetColumnFamilySet());
503 w.status = WriteBatchInternal::InsertInto(
504 &w, w.sequence, &column_family_memtables, &flush_scheduler_,
505 &trim_history_scheduler_,
506 write_options.ignore_missing_column_families, 0 /*log_number*/, this,
507 true /*concurrent_memtable_writes*/, seq_per_batch_, w.batch_cnt,
508 batch_per_txn_, write_options.memtable_insert_hint_per_batch);
509
510 PERF_TIMER_START(write_pre_and_post_process_time);
511 }
512
514 // we're responsible for exit batch group
515 // TODO(myabandeh): propagate status to write_group
516 auto last_sequence = w.write_group->last_sequence;
517 for (auto* tmp_w : *(w.write_group)) {
518 assert(tmp_w);
519 if (tmp_w->post_memtable_callback) {
520 Status tmp_s =
521 (*tmp_w->post_memtable_callback)(last_sequence, disable_memtable);
522 // TODO: propagate the execution status of post_memtable_callback to
523 // caller.
524 assert(tmp_s.ok());
525 }
526 }
527 versions_->SetLastSequence(last_sequence);
530 }
531 assert(w.state == WriteThread::STATE_COMPLETED);
532 // STATE_COMPLETED conditional below handles exit
533 }
534 if (w.state == WriteThread::STATE_COMPLETED) {
535 if (log_used != nullptr) {
536 *log_used = w.log_used;
537 }
538 if (seq_used != nullptr) {
539 *seq_used = w.sequence;
540 }
541 // write is complete and leader has updated sequence
542 return w.FinalStatus();
543 }
544 // else we are the leader of the write batch group
545 assert(w.state == WriteThread::STATE_GROUP_LEADER);
546 Status status;
547 // Once reaches this point, the current writer "w" will try to do its write
548 // job. It may also pick up some of the remaining writers in the "writers_"
549 // when it finds suitable, and finish them in the same write batch.
550 // This is how a write job could be done by the other writer.
551 WriteContext write_context;
552 LogContext log_context(write_options.sync);
553 WriteThread::WriteGroup write_group;
554 bool in_parallel_group = false;
555 uint64_t last_sequence = kMaxSequenceNumber;
556
557 assert(!two_write_queues_ || !disable_memtable);
558 {
559 // With concurrent writes we do preprocess only in the write thread that
560 // also does write to memtable to avoid sync issue on shared data structure
561 // with the other thread
562
563 // PreprocessWrite does its own perf timing.
564 PERF_TIMER_STOP(write_pre_and_post_process_time);
565
566 status = PreprocessWrite(write_options, &log_context, &write_context);
567 if (!two_write_queues_) {
568 // Assign it after ::PreprocessWrite since the sequence might advance
569 // inside it by WriteRecoverableState
570 last_sequence = versions_->LastSequence();
571 }
572
573 PERF_TIMER_START(write_pre_and_post_process_time);
574 }
575
576 // Add to log and apply to memtable. We can release the lock
577 // during this phase since &w is currently responsible for logging
578 // and protects against concurrent loggers and concurrent writes
579 // into memtables
580
581 TEST_SYNC_POINT("DBImpl::WriteImpl:BeforeLeaderEnters");
583 write_thread_.EnterAsBatchGroupLeader(&w, &write_group);
584 if (wbwi) {
585 assert(write_group.size == 1);
586 }
587
588 IOStatus io_s;
589 Status pre_release_cb_status;
590 if (status.ok()) {
591 // Rules for when we can update the memtable concurrently
592 // 1. supported by memtable
593 // 2. Puts are not okay if inplace_update_support
594 // 3. Merges are not okay
595 //
596 // Rules 1..2 are enforced by checking the options
597 // during startup (CheckConcurrentWritesSupported), so if
598 // options.allow_concurrent_memtable_write is true then they can be
599 // assumed to be true. Rule 3 is checked for each batch. We could
600 // relax rules 2 if we could prevent write batches from referring
601 // more than once to a particular key.
603 write_group.size > 1;
604 size_t total_count = 0;
605 size_t valid_batches = 0;
606 size_t total_byte_size = 0;
607 size_t pre_release_callback_cnt = 0;
608 for (auto* writer : write_group) {
609 assert(writer);
610 if (writer->CheckCallback(this)) {
611 valid_batches += writer->batch_cnt;
612 if (writer->ShouldWriteToMemtable()) {
613 total_count += WriteBatchInternal::Count(writer->batch);
614 total_byte_size = WriteBatchInternal::AppendedByteSize(
615 total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
616 parallel = parallel && !writer->batch->HasMerge();
617 }
618 if (writer->pre_release_callback) {
619 pre_release_callback_cnt++;
620 }
621 }
622 }
623 // TODO: this use of operator bool on `tracer_` can avoid unnecessary lock
624 // grabs but does not seem thread-safe.
625 if (tracer_) {
626 InstrumentedMutexLock lock(&trace_mutex_);
627 if (tracer_ && tracer_->IsWriteOrderPreserved()) {
628 for (auto* writer : write_group) {
629 if (writer->CallbackFailed()) {
630 continue;
631 }
632 // TODO: maybe handle the tracing status?
633 tracer_->Write(writer->batch).PermitUncheckedError();
634 }
635 }
636 }
637 // Note about seq_per_batch_: either disableWAL is set for the entire write
638 // group or not. In either case we inc seq for each write batch with no
639 // failed callback. This means that there could be a batch with
640 // disable_memtable in between; although we do not write this batch to
641 // memtable it still consumes a seq. Otherwise, if !seq_per_batch_, we inc
642 // the seq per valid written key to mem.
643 size_t seq_inc = seq_per_batch_ ? valid_batches : total_count;
644 if (wbwi) {
645 // Reserve sequence numbers for the ingested memtable. We need to reserve
646 // at lease this amount for recovery. During recovery,
647 // transactions do not commit by ingesting WBWI. The sequence number
648 // associated with the commit entry in WAL is used as the starting
649 // sequence number for inserting into memtable. We need to reserve
650 // enough sequence numbers here (at least the number of operations
651 // in write batch) to assign to memtable entries for this transaction.
652 // This prevents updates in different transactions from using out-of-order
653 // sequence numbers or the same key+seqno.
654 //
655 // WBWI ingestion requires not grouping writes, so we don't need to
656 // consider incrementing sequence number for WBWI from other writers.
657 seq_inc += wbwi->GetWriteBatch()->Count();
658 }
659
660 const bool concurrent_update = two_write_queues_;
661 // Update stats while we are an exclusive group leader, so we know
662 // that nobody else can be writing to these particular stats.
663 // We're optimistic, updating the stats before we successfully
664 // commit. That lets us release our leader status early.
665 auto stats = default_cf_internal_stats_;
666 stats->AddDBStats(InternalStats::kIntStatsNumKeysWritten, total_count,
667 concurrent_update);
668 RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
669 stats->AddDBStats(InternalStats::kIntStatsBytesWritten, total_byte_size,
670 concurrent_update);
671 RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
672 stats->AddDBStats(InternalStats::kIntStatsWriteDoneBySelf, 1,
673 concurrent_update);
674 RecordTick(stats_, WRITE_DONE_BY_SELF);
675 auto write_done_by_other = write_group.size - 1;
676 if (write_done_by_other > 0) {
677 stats->AddDBStats(InternalStats::kIntStatsWriteDoneByOther,
678 write_done_by_other, concurrent_update);
679 RecordTick(stats_, WRITE_DONE_BY_OTHER, write_done_by_other);
680 }
681 RecordInHistogram(stats_, BYTES_PER_WRITE, total_byte_size);
682
683 if (write_options.disableWAL) {
684 has_unpersisted_data_.store(true, std::memory_order_relaxed);
685 }
686
687 PERF_TIMER_STOP(write_pre_and_post_process_time);
688
689 if (!two_write_queues_) {
690 if (status.ok() && !write_options.disableWAL) {
691 assert(log_context.log_file_number_size);
692 LogFileNumberSize& log_file_number_size =
693 *(log_context.log_file_number_size);
694 PERF_TIMER_GUARD(write_wal_time);
695 io_s =
696 WriteToWAL(write_group, log_context.writer, log_used,
697 log_context.need_log_sync, log_context.need_log_dir_sync,
698 last_sequence + 1, log_file_number_size);
699 }
700 } else {
701 if (status.ok() && !write_options.disableWAL) {
702 PERF_TIMER_GUARD(write_wal_time);
703 // LastAllocatedSequence is increased inside WriteToWAL under
704 // wal_write_mutex_ to ensure ordered events in WAL
705 io_s = ConcurrentWriteToWAL(write_group, log_used, &last_sequence,
706 seq_inc);
707 } else {
708 // Otherwise we inc seq number for memtable writes
709 last_sequence = versions_->FetchAddLastAllocatedSequence(seq_inc);
710 }
711 }
712 status = io_s;
713 assert(last_sequence != kMaxSequenceNumber);
714 const SequenceNumber current_sequence = last_sequence + 1;
715 last_sequence += seq_inc;
716
717 if (log_context.need_log_sync) {
718 VersionEdit synced_wals;
720 if (status.ok()) {
721 MarkLogsSynced(logfile_number_, log_context.need_log_dir_sync,
722 &synced_wals);
723 } else {
724 MarkLogsNotSynced(logfile_number_);
725 }
727 if (status.ok() && synced_wals.IsWalAddition()) {
728 InstrumentedMutexLock l(&mutex_);
729 // TODO: plumb Env::IOActivity, Env::IOPriority
730 const ReadOptions read_options;
731 status = ApplyWALToManifest(read_options, write_options, &synced_wals);
732 }
733
734 // Requesting sync with two_write_queues_ is expected to be very rare. We
735 // hence provide a simple implementation that is not necessarily
736 // efficient.
737 if (status.ok() && two_write_queues_) {
738 if (manual_wal_flush_) {
739 status = FlushWAL(true);
740 } else {
741 status = SyncWAL();
742 }
743 }
744 }
745
746 // PreReleaseCallback is called after WAL write and before memtable write
747 if (status.ok()) {
748 SequenceNumber next_sequence = current_sequence;
749 size_t index = 0;
750 // Note: the logic for advancing seq here must be consistent with the
751 // logic in WriteBatchInternal::InsertInto(write_group...) as well as
752 // with WriteBatchInternal::InsertInto(write_batch...) that is called on
753 // the merged batch during recovery from the WAL.
754 for (auto* writer : write_group) {
755 if (writer->CallbackFailed()) {
756 continue;
757 }
758 writer->sequence = next_sequence;
759 if (writer->pre_release_callback) {
760 Status ws = writer->pre_release_callback->Callback(
761 writer->sequence, disable_memtable, writer->log_used, index++,
762 pre_release_callback_cnt);
763 if (!ws.ok()) {
764 status = pre_release_cb_status = ws;
765 break;
766 }
767 }
768 if (seq_per_batch_) {
769 assert(writer->batch_cnt);
770 next_sequence += writer->batch_cnt;
771 } else if (writer->ShouldWriteToMemtable()) {
772 next_sequence += WriteBatchInternal::Count(writer->batch);
773 }
774 }
775 }
776
777 if (status.ok()) {
778 PERF_TIMER_FOR_WAIT_GUARD(write_memtable_time);
779
780 if (!parallel) {
781 // w.sequence will be set inside InsertInto
782 w.status = WriteBatchInternal::InsertInto(
783 write_group, current_sequence, column_family_memtables_.get(),
784 &flush_scheduler_, &trim_history_scheduler_,
785 write_options.ignore_missing_column_families,
786 0 /*recovery_log_number*/, this, parallel, seq_per_batch_,
787 batch_per_txn_);
788 } else {
789 write_group.last_sequence = last_sequence;
791 in_parallel_group = true;
792
793 // Each parallel follower is doing each own writes. The leader should
794 // also do its own.
795 if (w.ShouldWriteToMemtable()) {
796 ColumnFamilyMemTablesImpl column_family_memtables(
797 versions_->GetColumnFamilySet());
798 assert(w.sequence == current_sequence);
799 w.status = WriteBatchInternal::InsertInto(
800 &w, w.sequence, &column_family_memtables, &flush_scheduler_,
801 &trim_history_scheduler_,
802 write_options.ignore_missing_column_families, 0 /*log_number*/,
803 this, true /*concurrent_memtable_writes*/, seq_per_batch_,
804 w.batch_cnt, batch_per_txn_,
805 write_options.memtable_insert_hint_per_batch);
806 }
807 }
808 if (seq_used != nullptr) {
809 *seq_used = w.sequence;
810 }
811 }
812 }
813 PERF_TIMER_START(write_pre_and_post_process_time);
814
815 if (!io_s.ok()) {
816 // Check WriteToWAL status
817 WALIOStatusCheck(io_s);
818 }
819 if (!w.CallbackFailed()) {
820 if (!io_s.ok()) {
821 assert(pre_release_cb_status.ok());
822 } else {
823 WriteStatusCheck(pre_release_cb_status);
824 }
825 } else {
826 assert(pre_release_cb_status.ok());
827 }
828
829 bool should_exit_batch_group = true;
830 if (in_parallel_group) {
831 // CompleteParallelWorker returns true if this thread should
832 // handle exit, false means somebody else did
833 should_exit_batch_group = write_thread_.CompleteParallelMemTableWriter(&w);
834 }
835 if (wbwi) {
836 if (status.ok() && w.status.ok()) {
837 // w.batch contains (potentially empty) commit time batch updates,
838 // only ingest wbwi if w.batch is applied to memtable successfully
839 assert(wbwi->GetWriteBatch()->Count() > 0);
840
841 uint32_t memtable_update_count = w.batch->Count();
842 SequenceNumber lb = versions_->LastSequence() + memtable_update_count + 1;
843 SequenceNumber ub = versions_->LastSequence() + memtable_update_count +
844 wbwi->GetWriteBatch()->Count();
845 assert(ub == last_sequence);
846 if (two_write_queues_) {
847 assert(ub <= versions_->LastAllocatedSequence());
848 }
849 status = IngestWBWI(wbwi, {/*lower_bound=*/lb, /*upper_bound=*/ub},
850 prep_log, last_sequence,
851 /*memtable_updated=*/memtable_update_count > 0,
852 write_options.ignore_missing_column_families);
853 }
854 }
855
856 if (should_exit_batch_group) {
857 if (status.ok()) {
858 for (auto* tmp_w : write_group) {
859 assert(tmp_w);
860 if (tmp_w->post_memtable_callback) {
861 Status tmp_s =
862 (*tmp_w->post_memtable_callback)(last_sequence, disable_memtable);
863 // TODO: propagate the execution status of post_memtable_callback to
864 // caller.
865 assert(tmp_s.ok());
866 }
867 }
868 // Note: if we are to resume after non-OK statuses we need to revisit how
869 // we react to non-OK statuses here.
870 versions_->SetLastSequence(last_sequence);
871 }
873 write_thread_.ExitAsBatchGroupLeader(write_group, status);
874 }
875
876 if (status.ok()) {
877 status = w.FinalStatus();
878 }
879 return status;
880}
Status WriteImplWALOnly(WriteThread *write_thread, const WriteOptions &options, WriteBatch *updates, WriteCallback *callback, UserWriteCallback *user_write_cb, uint64_t *log_used, const uint64_t log_ref, uint64_t *seq_used, const size_t sub_batch_cnt, PreReleaseCallback *pre_release_callback, const AssignOrder assign_order, const PublishLastSeq publish_last_seq, const bool disable_memtable)
Status PipelinedWriteImpl(const WriteOptions &options, WriteBatch *updates, WriteCallback *callback=nullptr, UserWriteCallback *user_write_cb=nullptr, uint64_t *log_used=nullptr, uint64_t log_ref=0, bool disable_memtable=false, uint64_t *seq_used=nullptr)
Status IngestWBWI(std::shared_ptr< WriteBatchWithIndex > wbwi, const WBWIMemTable::SeqnoRange &assigned_seqno, uint64_t min_prep_log, SequenceNumber last_seqno, bool memtable_updated, bool ignore_missing_cf)
Status UnorderedWriteMemtable(const WriteOptions &write_options, WriteBatch *my_batch, WriteCallback *callback, uint64_t log_ref, SequenceNumber seq, const size_t sub_batch_cnt)
Status ThrottleLowPriWritesIfNeeded(const WriteOptions &write_options, WriteBatch *my_batch)
IOStatus ConcurrentWriteToWAL(const WriteThread::WriteGroup &write_group, uint64_t *log_used, SequenceNumber *last_sequence, size_t seq_inc)
void ExitAsBatchGroupFollower(Writer *w)
std::shared_ptr< Cache > row_cache
Definition db_options.h:78
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteImplWALOnly()

Status ROCKSDB_NAMESPACE::DBImpl::WriteImplWALOnly ( WriteThread * write_thread,
const WriteOptions & options,
WriteBatch * updates,
WriteCallback * callback,
UserWriteCallback * user_write_cb,
uint64_t * log_used,
const uint64_t log_ref,
uint64_t * seq_used,
const size_t sub_batch_cnt,
PreReleaseCallback * pre_release_callback,
const AssignOrder assign_order,
const PublishLastSeq publish_last_seq,
const bool disable_memtable )
protected

db_impl_write.cc 파일의 1128 번째 라인에서 정의되었습니다.

1134 {
1135 PERF_TIMER_GUARD(write_pre_and_post_process_time);
1136 WriteThread::Writer w(write_options, my_batch, callback, user_write_cb,
1137 log_ref, disable_memtable, sub_batch_cnt,
1138 pre_release_callback);
1139 StopWatch write_sw(immutable_db_options_.clock, stats_, DB_WRITE);
1140
1141 write_thread->JoinBatchGroup(&w);
1142 assert(w.state != WriteThread::STATE_PARALLEL_MEMTABLE_WRITER);
1143 if (w.state == WriteThread::STATE_COMPLETED) {
1144 if (log_used != nullptr) {
1145 *log_used = w.log_used;
1146 }
1147 if (seq_used != nullptr) {
1148 *seq_used = w.sequence;
1149 }
1150 return w.FinalStatus();
1151 }
1152 // else we are the leader of the write batch group
1153 assert(w.state == WriteThread::STATE_GROUP_LEADER);
1154
1155 if (publish_last_seq == kDoPublishLastSeq) {
1156 // Currently we only use kDoPublishLastSeq in unordered_write
1158
1159 // TODO(myabandeh): Make preliminary checks thread-safe so we could do them
1160 // without paying the cost of obtaining the mutex.
1161 LogContext log_context;
1162 WriteContext write_context;
1163 Status status =
1164 PreprocessWrite(write_options, &log_context, &write_context);
1166
1167 if (!status.ok()) {
1168 WriteThread::WriteGroup write_group;
1169 write_thread->EnterAsBatchGroupLeader(&w, &write_group);
1170 write_thread->ExitAsBatchGroupLeader(write_group, status);
1171 return status;
1172 }
1173 } else {
1174 PERF_TIMER_STOP(write_pre_and_post_process_time);
1175 PERF_TIMER_FOR_WAIT_GUARD(write_delay_time);
1176 InstrumentedMutexLock lock(&mutex_);
1177 Status status =
1178 DelayWrite(/*num_bytes=*/0ull, *write_thread, write_options);
1179 PERF_TIMER_STOP(write_delay_time);
1180 PERF_TIMER_START(write_pre_and_post_process_time);
1181 if (!status.ok()) {
1182 WriteThread::WriteGroup write_group;
1183 write_thread->EnterAsBatchGroupLeader(&w, &write_group);
1184 write_thread->ExitAsBatchGroupLeader(write_group, status);
1185 return status;
1186 }
1187 }
1188
1189 WriteThread::WriteGroup write_group;
1190 uint64_t last_sequence;
1191 write_thread->EnterAsBatchGroupLeader(&w, &write_group);
1192
1193 size_t pre_release_callback_cnt = 0;
1194 size_t total_byte_size = 0;
1195 for (auto* writer : write_group) {
1196 assert(writer);
1197 if (writer->CheckCallback(this)) {
1198 total_byte_size = WriteBatchInternal::AppendedByteSize(
1199 total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
1200 if (writer->pre_release_callback) {
1201 pre_release_callback_cnt++;
1202 }
1203 }
1204 }
1205
1206 // Note: no need to update last_batch_group_size_ here since the batch writes
1207 // to WAL only
1208 // TODO: this use of operator bool on `tracer_` can avoid unnecessary lock
1209 // grabs but does not seem thread-safe.
1210 if (tracer_) {
1211 InstrumentedMutexLock lock(&trace_mutex_);
1212 if (tracer_ != nullptr && tracer_->IsWriteOrderPreserved()) {
1213 for (auto* writer : write_group) {
1214 if (writer->CallbackFailed()) {
1215 continue;
1216 }
1217 // TODO: maybe handle the tracing status?
1218 tracer_->Write(writer->batch).PermitUncheckedError();
1219 }
1220 }
1221 }
1222
1223 const bool concurrent_update = true;
1224 // Update stats while we are an exclusive group leader, so we know
1225 // that nobody else can be writing to these particular stats.
1226 // We're optimistic, updating the stats before we successfully
1227 // commit. That lets us release our leader status early.
1228 auto stats = default_cf_internal_stats_;
1229 stats->AddDBStats(InternalStats::kIntStatsBytesWritten, total_byte_size,
1230 concurrent_update);
1231 RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
1232 stats->AddDBStats(InternalStats::kIntStatsWriteDoneBySelf, 1,
1233 concurrent_update);
1234 RecordTick(stats_, WRITE_DONE_BY_SELF);
1235 auto write_done_by_other = write_group.size - 1;
1236 if (write_done_by_other > 0) {
1237 stats->AddDBStats(InternalStats::kIntStatsWriteDoneByOther,
1238 write_done_by_other, concurrent_update);
1239 RecordTick(stats_, WRITE_DONE_BY_OTHER, write_done_by_other);
1240 }
1241 RecordInHistogram(stats_, BYTES_PER_WRITE, total_byte_size);
1242
1243 PERF_TIMER_STOP(write_pre_and_post_process_time);
1244
1245 PERF_TIMER_GUARD(write_wal_time);
1246 // LastAllocatedSequence is increased inside WriteToWAL under
1247 // wal_write_mutex_ to ensure ordered events in WAL
1248 size_t seq_inc = 0 /* total_count */;
1249 if (assign_order == kDoAssignOrder) {
1250 size_t total_batch_cnt = 0;
1251 for (auto* writer : write_group) {
1252 assert(writer->batch_cnt || !seq_per_batch_);
1253 if (!writer->CallbackFailed()) {
1254 total_batch_cnt += writer->batch_cnt;
1255 }
1256 }
1257 seq_inc = total_batch_cnt;
1258 }
1259 Status status;
1260 if (!write_options.disableWAL) {
1261 IOStatus io_s =
1262 ConcurrentWriteToWAL(write_group, log_used, &last_sequence, seq_inc);
1263 status = io_s;
1264 // last_sequence may not be set if there is an error
1265 // This error checking and return is moved up to avoid using uninitialized
1266 // last_sequence.
1267 if (!io_s.ok()) {
1268 WALIOStatusCheck(io_s);
1269 write_thread->ExitAsBatchGroupLeader(write_group, status);
1270 return status;
1271 }
1272 } else {
1273 // Otherwise we inc seq number to do solely the seq allocation
1274 last_sequence = versions_->FetchAddLastAllocatedSequence(seq_inc);
1275 }
1276
1277 size_t memtable_write_cnt = 0;
1278 auto curr_seq = last_sequence + 1;
1279 for (auto* writer : write_group) {
1280 if (writer->CallbackFailed()) {
1281 continue;
1282 }
1283 writer->sequence = curr_seq;
1284 if (assign_order == kDoAssignOrder) {
1285 assert(writer->batch_cnt || !seq_per_batch_);
1286 curr_seq += writer->batch_cnt;
1287 }
1288 if (!writer->disable_memtable) {
1289 memtable_write_cnt++;
1290 }
1291 // else seq advances only by memtable writes
1292 }
1293 if (status.ok() && write_options.sync) {
1294 assert(!write_options.disableWAL);
1295 // Requesting sync with two_write_queues_ is expected to be very rare. We
1296 // hance provide a simple implementation that is not necessarily efficient.
1297 if (manual_wal_flush_) {
1298 status = FlushWAL(true);
1299 } else {
1300 status = SyncWAL();
1301 }
1302 }
1303 PERF_TIMER_START(write_pre_and_post_process_time);
1304
1305 if (!w.CallbackFailed()) {
1306 WriteStatusCheck(status);
1307 }
1308 if (status.ok()) {
1309 size_t index = 0;
1310 for (auto* writer : write_group) {
1311 if (!writer->CallbackFailed() && writer->pre_release_callback) {
1312 assert(writer->sequence != kMaxSequenceNumber);
1313 Status ws = writer->pre_release_callback->Callback(
1314 writer->sequence, disable_memtable, writer->log_used, index++,
1315 pre_release_callback_cnt);
1316 if (!ws.ok()) {
1317 status = ws;
1318 break;
1319 }
1320 }
1321 }
1322 }
1323 if (publish_last_seq == kDoPublishLastSeq) {
1324 versions_->SetLastSequence(last_sequence + seq_inc);
1325 // Currently we only use kDoPublishLastSeq in unordered_write
1327 }
1328 if (immutable_db_options_.unordered_write && status.ok()) {
1329 pending_memtable_writes_ += memtable_write_cnt;
1330 }
1331 write_thread->ExitAsBatchGroupLeader(write_group, status);
1332 if (status.ok()) {
1333 status = w.FinalStatus();
1334 }
1335 if (seq_used != nullptr) {
1336 *seq_used = w.sequence;
1337 }
1338 return status;
1339}
void WriteStatusCheckOnLocked(const Status &status)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteLevel0TableForRecovery()

Status ROCKSDB_NAMESPACE::DBImpl::WriteLevel0TableForRecovery ( int job_id,
ColumnFamilyData * cfd,
MemTable * mem,
VersionEdit * edit )
private

db_impl_open.cc 파일의 1647 번째 라인에서 정의되었습니다.

1648 {
1649 mutex_.AssertHeld();
1650 assert(cfd);
1651 assert(cfd->imm());
1652 // The immutable memtable list must be empty.
1653 assert(std::numeric_limits<uint64_t>::max() ==
1654 cfd->imm()->GetEarliestMemTableID());
1655
1656 const uint64_t start_micros = immutable_db_options_.clock->NowMicros();
1657
1658 FileMetaData meta;
1659 std::vector<BlobFileAddition> blob_file_additions;
1660
1661 std::unique_ptr<std::list<uint64_t>::iterator> pending_outputs_inserted_elem(
1662 new std::list<uint64_t>::iterator(
1664 meta.fd = FileDescriptor(versions_->NewFileNumber(), 0, 0);
1665 ReadOptions ro;
1666 ro.total_order_seek = true;
1667 ro.io_activity = Env::IOActivity::kDBOpen;
1668 Arena arena;
1669 Status s;
1670 TableProperties table_properties;
1671 const auto* ucmp = cfd->internal_comparator().user_comparator();
1672 assert(ucmp);
1673 const size_t ts_sz = ucmp->timestamp_size();
1674 const bool logical_strip_timestamp =
1675 ts_sz > 0 && !cfd->ioptions()->persist_user_defined_timestamps;
1676 {
1677 ScopedArenaPtr<InternalIterator> iter(
1678 logical_strip_timestamp
1679 ? mem->NewTimestampStrippingIterator(
1680 ro, /*seqno_to_time_mapping=*/nullptr, &arena,
1681 /*prefix_extractor=*/nullptr, ts_sz)
1682 : mem->NewIterator(ro, /*seqno_to_time_mapping=*/nullptr, &arena,
1683 /*prefix_extractor=*/nullptr,
1684 /*for_flush=*/true));
1686 "[%s] [WriteLevel0TableForRecovery]"
1687 " Level-0 table #%" PRIu64 ": started",
1688 cfd->GetName().c_str(), meta.fd.GetNumber());
1689
1690 // Get the latest mutable cf options while the mutex is still locked
1691 const MutableCFOptions mutable_cf_options =
1692 *cfd->GetLatestMutableCFOptions();
1693 bool paranoid_file_checks =
1694 cfd->GetLatestMutableCFOptions()->paranoid_file_checks;
1695
1696 int64_t _current_time = 0;
1698 .PermitUncheckedError(); // ignore error
1699 const uint64_t current_time = static_cast<uint64_t>(_current_time);
1700 meta.oldest_ancester_time = current_time;
1701 meta.epoch_number = cfd->NewEpochNumber();
1702 {
1703 auto write_hint =
1704 cfd->current()->storage_info()->CalculateSSTWriteHint(/*level=*/0);
1705 mutex_.Unlock();
1706
1707 SequenceNumber earliest_write_conflict_snapshot;
1708 std::vector<SequenceNumber> snapshot_seqs =
1709 snapshots_.GetAll(&earliest_write_conflict_snapshot);
1710 SequenceNumber earliest_snapshot =
1711 (snapshot_seqs.empty() ? kMaxSequenceNumber : snapshot_seqs.at(0));
1712 auto snapshot_checker = snapshot_checker_.get();
1713 if (use_custom_gc_ && snapshot_checker == nullptr) {
1714 snapshot_checker = DisableGCSnapshotChecker::Instance();
1715 }
1716 std::vector<std::unique_ptr<FragmentedRangeTombstoneIterator>>
1717 range_del_iters;
1718 auto range_del_iter =
1719 logical_strip_timestamp
1720 ? mem->NewTimestampStrippingRangeTombstoneIterator(
1721 ro, kMaxSequenceNumber, ts_sz)
1722 // This is called during recovery, where a live memtable is
1723 // flushed directly. In this case, no fragmented tombstone list is
1724 // cached in this memtable yet.
1725 : mem->NewRangeTombstoneIterator(ro, kMaxSequenceNumber,
1726 false /* immutable_memtable */);
1727 if (range_del_iter != nullptr) {
1728 range_del_iters.emplace_back(range_del_iter);
1729 }
1730
1731 IOStatus io_s;
1732 const ReadOptions read_option(Env::IOActivity::kDBOpen);
1733 const WriteOptions write_option(Env::IO_HIGH, Env::IOActivity::kDBOpen);
1734
1735 TableBuilderOptions tboptions(
1736 *cfd->ioptions(), mutable_cf_options, read_option, write_option,
1737 cfd->internal_comparator(), cfd->internal_tbl_prop_coll_factories(),
1738 GetCompressionFlush(*cfd->ioptions(), mutable_cf_options),
1739 mutable_cf_options.compression_opts, cfd->GetID(), cfd->GetName(),
1740 0 /* level */, current_time /* newest_key_time */,
1741 false /* is_bottommost */, TableFileCreationReason::kRecovery,
1742 0 /* oldest_key_time */, 0 /* file_creation_time */, db_id_,
1743 db_session_id_, 0 /* target_file_size */, meta.fd.GetNumber(),
1744 kMaxSequenceNumber);
1745 Version* version = cfd->current();
1746 version->Ref();
1747 uint64_t num_input_entries = 0;
1748 s = BuildTable(dbname_, versions_.get(), immutable_db_options_, tboptions,
1749 file_options_for_compaction_, cfd->table_cache(),
1750 iter.get(), std::move(range_del_iters), &meta,
1751 &blob_file_additions, snapshot_seqs, earliest_snapshot,
1752 earliest_write_conflict_snapshot, kMaxSequenceNumber,
1753 snapshot_checker, paranoid_file_checks,
1754 cfd->internal_stats(), &io_s, io_tracer_,
1755 BlobFileCreationReason::kRecovery,
1756 nullptr /* seqno_to_time_mapping */, &event_logger_,
1757 job_id, nullptr /* table_properties */, write_hint,
1758 nullptr /*full_history_ts_low*/, &blob_callback_, version,
1759 &num_input_entries);
1760 version->Unref();
1763 "[%s] [WriteLevel0TableForRecovery]"
1764 " Level-0 table #%" PRIu64 ": %" PRIu64 " bytes %s",
1765 cfd->GetName().c_str(), meta.fd.GetNumber(),
1766 meta.fd.GetFileSize(), s.ToString().c_str());
1767 mutex_.Lock();
1768
1769 // TODO(AR) is this ok?
1770 if (!io_s.ok() && s.ok()) {
1771 s = io_s;
1772 }
1773
1774 uint64_t total_num_entries = mem->NumEntries();
1775 if (s.ok() && total_num_entries != num_input_entries) {
1776 std::string msg = "Expected " + std::to_string(total_num_entries) +
1777 " entries in memtable, but read " +
1778 std::to_string(num_input_entries);
1780 "[%s] [JOB %d] Level-0 flush during recover: %s",
1781 cfd->GetName().c_str(), job_id, msg.c_str());
1783 s = Status::Corruption(msg);
1784 }
1785 }
1786 }
1787 }
1788 ReleaseFileNumberFromPendingOutputs(pending_outputs_inserted_elem);
1789
1790 // Note that if file_size is zero, the file has been deleted and
1791 // should not be added to the manifest.
1792 const bool has_output = meta.fd.GetFileSize() > 0;
1793
1794 constexpr int level = 0;
1795
1796 if (s.ok() && has_output) {
1797 edit->AddFile(level, meta.fd.GetNumber(), meta.fd.GetPathId(),
1798 meta.fd.GetFileSize(), meta.smallest, meta.largest,
1799 meta.fd.smallest_seqno, meta.fd.largest_seqno,
1800 meta.marked_for_compaction, meta.temperature,
1801 meta.oldest_blob_file_number, meta.oldest_ancester_time,
1802 meta.file_creation_time, meta.epoch_number,
1803 meta.file_checksum, meta.file_checksum_func_name,
1804 meta.unique_id, meta.compensated_range_deletion_size,
1805 meta.tail_size, meta.user_defined_timestamps_persisted);
1806
1807 for (const auto& blob : blob_file_additions) {
1808 edit->AddBlobFile(blob);
1809 }
1810
1811 // For UDT in memtable only feature, move up the cutoff timestamp whenever
1812 // a flush happens.
1813 if (logical_strip_timestamp) {
1814 Slice mem_newest_udt = mem->GetNewestUDT();
1815 std::string full_history_ts_low = cfd->GetFullHistoryTsLow();
1816 if (full_history_ts_low.empty() ||
1817 ucmp->CompareTimestamp(mem_newest_udt, full_history_ts_low) >= 0) {
1818 std::string new_full_history_ts_low;
1819 GetFullHistoryTsLowFromU64CutoffTs(&mem_newest_udt,
1820 &new_full_history_ts_low);
1821 edit->SetFullHistoryTsLow(new_full_history_ts_low);
1822 }
1823 }
1824 }
1825
1826 InternalStats::CompactionStats stats(CompactionReason::kFlush, 1);
1827 stats.micros = immutable_db_options_.clock->NowMicros() - start_micros;
1828
1829 if (has_output) {
1830 stats.bytes_written = meta.fd.GetFileSize();
1831 stats.num_output_files = 1;
1832 }
1833
1834 const auto& blobs = edit->GetBlobFileAdditions();
1835 for (const auto& blob : blobs) {
1836 stats.bytes_written_blob += blob.GetTotalBlobBytes();
1837 }
1838
1839 stats.num_output_files_blob = static_cast<int>(blobs.size());
1840
1841 cfd->internal_stats()->AddCompactionStats(level, Env::Priority::USER, stats);
1842 cfd->internal_stats()->AddCFStats(
1843 InternalStats::BYTES_FLUSHED,
1844 stats.bytes_written + stats.bytes_written_blob);
1845 RecordTick(stats_, COMPACT_WRITE_BYTES, meta.fd.GetFileSize());
1846 return s;
1847}
Status BuildTable(const std::string &dbname, VersionSet *versions, const ImmutableDBOptions &db_options, const TableBuilderOptions &tboptions, const FileOptions &file_options, TableCache *table_cache, InternalIterator *iter, std::vector< std::unique_ptr< FragmentedRangeTombstoneIterator > > range_del_iters, FileMetaData *meta, std::vector< BlobFileAddition > *blob_file_additions, std::vector< SequenceNumber > snapshots, SequenceNumber earliest_snapshot, SequenceNumber earliest_write_conflict_snapshot, SequenceNumber job_snapshot, SnapshotChecker *snapshot_checker, bool paranoid_file_checks, InternalStats *internal_stats, IOStatus *io_status, const std::shared_ptr< IOTracer > &io_tracer, BlobFileCreationReason blob_creation_reason, UnownedPtr< const SeqnoToTimeMapping > seqno_to_time_mapping, EventLogger *event_logger, int job_id, TableProperties *table_properties, Env::WriteLifeTimeHint write_hint, const std::string *full_history_ts_low, BlobFileCompletionCallback *blob_callback, Version *version, uint64_t *num_input_entries, uint64_t *memtable_payload_bytes, uint64_t *memtable_garbage_bytes)
Definition builder.cc:59
void GetFullHistoryTsLowFromU64CutoffTs(Slice *cutoff_ts, std::string *full_history_ts_low)
Definition udt_util.cc:424
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteOptionsFile()

Status ROCKSDB_NAMESPACE::DBImpl::WriteOptionsFile ( const WriteOptions & write_options,
bool db_mutex_already_held )
protected

db_impl.cc 파일의 5506 번째 라인에서 정의되었습니다.

5507 {
5509
5510 if (db_mutex_already_held) {
5511 mutex_.AssertHeld();
5512 } else {
5513 mutex_.Lock();
5514 }
5515
5516 std::vector<std::string> cf_names;
5517 std::vector<ColumnFamilyOptions> cf_opts;
5518
5519 // This part requires mutex to protect the column family options
5520 for (auto cfd : *versions_->GetColumnFamilySet()) {
5521 if (cfd->IsDropped()) {
5522 continue;
5523 }
5524 cf_names.push_back(cfd->GetName());
5525 cf_opts.push_back(cfd->GetLatestCFOptions());
5526 }
5527
5528 DBOptions db_options =
5529 BuildDBOptions(immutable_db_options_, mutable_db_options_);
5530
5531 // Unlock during expensive operations.
5532 mutex_.Unlock();
5533
5534 TEST_SYNC_POINT("DBImpl::WriteOptionsFile:1");
5535 TEST_SYNC_POINT("DBImpl::WriteOptionsFile:2");
5536 TEST_SYNC_POINT_CALLBACK("DBImpl::WriteOptionsFile:PersistOptions",
5537 &db_options);
5538
5539 std::string file_name =
5540 TempOptionsFileName(GetName(), versions_->NewFileNumber());
5541 Status s = PersistRocksDBOptions(write_options, db_options, cf_names, cf_opts,
5542 file_name, fs_.get());
5543
5544 if (s.ok()) {
5545 s = RenameTempFileToOptionsFile(file_name,
5546 db_options.compaction_service != nullptr);
5547 }
5548
5549 if (!s.ok() && GetEnv()->FileExists(file_name).ok()) {
5550 if (!GetEnv()->DeleteFile(file_name).ok()) {
5552 "Unable to delete temp options file %s",
5553 file_name.c_str());
5554 }
5555 }
5556
5557 if (!s.ok()) {
5559 "Unnable to persist options -- %s", s.ToString().c_str());
5561 s = Status::IOError("Unable to persist options.", s.ToString().c_str());
5562 } else {
5563 // Ignore error
5564 s = Status::OK();
5565 }
5566 }
5567
5568 // Restore lock if appropriate
5569 if (db_mutex_already_held) {
5570 mutex_.Lock();
5571 }
5572 return s;
5573}
Status DeleteFile(std::string name) override
Definition db_impl.cc:4881
Status RenameTempFileToOptionsFile(const std::string &file_name, bool is_remote_compaction_enabled)
Definition db_impl.cc:5623
std::string TempOptionsFileName(const std::string &dbname, uint64_t file_num)
Definition filename.cc:237
Status PersistRocksDBOptions(const WriteOptions &write_options, const DBOptions &db_opt, const std::vector< std::string > &cf_names, const std::vector< ColumnFamilyOptions > &cf_opts, const std::string &file_name, FileSystem *fs)
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteRecoverableState()

Status ROCKSDB_NAMESPACE::DBImpl::WriteRecoverableState ( )
protected

db_impl_write.cc 파일의 1788 번째 라인에서 정의되었습니다.

1788 {
1789 mutex_.AssertHeld();
1790 if (!cached_recoverable_state_empty_) {
1791 // Only for write-prepared and write-unprepared.
1792 assert(seq_per_batch_);
1793 bool dont_care_bool;
1794 SequenceNumber next_seq;
1795 if (two_write_queues_) {
1797 }
1798 SequenceNumber seq;
1799 if (two_write_queues_) {
1800 seq = versions_->FetchAddLastAllocatedSequence(0);
1801 } else {
1802 seq = versions_->LastSequence();
1803 }
1804 WriteBatchInternal::SetSequence(&cached_recoverable_state_, seq + 1);
1805 auto status = WriteBatchInternal::InsertInto(
1806 &cached_recoverable_state_, column_family_memtables_.get(),
1807 &flush_scheduler_, &trim_history_scheduler_, true,
1808 0 /*recovery_log_number*/, this, false /* concurrent_memtable_writes */,
1809 &next_seq, &dont_care_bool, seq_per_batch_);
1810 auto last_seq = next_seq - 1;
1811 if (two_write_queues_) {
1812 versions_->FetchAddLastAllocatedSequence(last_seq - seq);
1813 versions_->SetLastPublishedSequence(last_seq);
1814 }
1815 versions_->SetLastSequence(last_seq);
1816 if (two_write_queues_) {
1818 }
1819 if (status.ok() && recoverable_state_pre_release_callback_) {
1820 const bool DISABLE_MEMTABLE = true;
1821 for (uint64_t sub_batch_seq = seq + 1;
1822 sub_batch_seq < next_seq && status.ok(); sub_batch_seq++) {
1823 uint64_t const no_log_num = 0;
1824 // Unlock it since the callback might end up locking mutex. e.g.,
1825 // AddCommitted -> AdvanceMaxEvictedSeq -> GetSnapshotListFromDB
1826 mutex_.Unlock();
1827 status = recoverable_state_pre_release_callback_->Callback(
1828 sub_batch_seq, !DISABLE_MEMTABLE, no_log_num, 0, 1);
1829 mutex_.Lock();
1830 }
1831 }
1832 if (status.ok()) {
1835 } else {
1836 // FIXME: !ok status is untested
1837 }
1838 return status;
1839 }
1840 return Status::OK();
1841}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteStatusCheck()

void ROCKSDB_NAMESPACE::DBImpl::WriteStatusCheck ( const Status & status)
private

db_impl_write.cc 파일의 1353 번째 라인에서 정의되었습니다.

1353 {
1354 // Is setting bg_error_ enough here? This will at least stop
1355 // compaction and fail any further writes.
1356 assert(!status.IsIOFenced() || !error_handler_.GetBGError().ok());
1357 if (immutable_db_options_.paranoid_checks && !status.ok() &&
1358 !status.IsBusy() && !status.IsIncomplete()) {
1359 mutex_.Lock();
1360 // Maybe change the return status to void?
1361 error_handler_.SetBGError(status, BackgroundErrorReason::kWriteCallback);
1362 mutex_.Unlock();
1363 }
1364}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteStatusCheckOnLocked()

void ROCKSDB_NAMESPACE::DBImpl::WriteStatusCheckOnLocked ( const Status & status)
private

db_impl_write.cc 파일의 1341 번째 라인에서 정의되었습니다.

1341 {
1342 // Is setting bg_error_ enough here? This will at least stop
1343 // compaction and fail any further writes.
1344 InstrumentedMutexLock l(&mutex_);
1345 assert(!status.IsIOFenced() || !error_handler_.GetBGError().ok());
1346 if (immutable_db_options_.paranoid_checks && !status.ok() &&
1347 !status.IsBusy() && !status.IsIncomplete()) {
1348 // Maybe change the return status to void?
1349 error_handler_.SetBGError(status, BackgroundErrorReason::kWriteCallback);
1350 }
1351}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteToWAL() [1/2]

IOStatus ROCKSDB_NAMESPACE::DBImpl::WriteToWAL ( const WriteBatch & merged_batch,
const WriteOptions & write_options,
log::Writer * log_writer,
uint64_t * log_used,
uint64_t * log_size,
LogFileNumberSize & log_file_number_size )
private

db_impl_write.cc 파일의 1557 번째 라인에서 정의되었습니다.

1561 {
1562 assert(log_size != nullptr);
1563
1564 Slice log_entry = WriteBatchInternal::Contents(&merged_batch);
1565 TEST_SYNC_POINT_CALLBACK("DBImpl::WriteToWAL:log_entry", &log_entry);
1566 auto s = merged_batch.VerifyChecksum();
1567 if (!s.ok()) {
1568 return status_to_io_status(std::move(s));
1569 }
1570 *log_size = log_entry.size();
1571 // When two_write_queues_ WriteToWAL has to be protected from concurretn calls
1572 // from the two queues anyway and log_write_mutex_ is already held. Otherwise
1573 // if manual_wal_flush_ is enabled we need to protect log_writer->AddRecord
1574 // from possible concurrent calls via the FlushWAL by the application.
1575 const bool needs_locking = manual_wal_flush_ && !two_write_queues_;
1576 // Due to performance cocerns of missed branch prediction penalize the new
1577 // manual_wal_flush_ feature (by UNLIKELY) instead of the more common case
1578 // when we do not need any locking.
1579 if (UNLIKELY(needs_locking)) {
1581 }
1582 IOStatus io_s = log_writer->MaybeAddUserDefinedTimestampSizeRecord(
1583 write_options, versions_->GetColumnFamiliesTimestampSizeForRecord());
1584 if (!io_s.ok()) {
1585 return io_s;
1586 }
1587 io_s = log_writer->AddRecord(write_options, log_entry);
1588
1589 if (UNLIKELY(needs_locking)) {
1591 }
1592 if (log_used != nullptr) {
1593 *log_used = logfile_number_;
1594 }
1595 total_log_size_ += log_entry.size();
1596 log_file_number_size.AddSize(*log_size);
1597 log_empty_ = false;
1598
1599 return io_s;
1600}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteToWAL() [2/2]

IOStatus ROCKSDB_NAMESPACE::DBImpl::WriteToWAL ( const WriteThread::WriteGroup & write_group,
log::Writer * log_writer,
uint64_t * log_used,
bool need_log_sync,
bool need_log_dir_sync,
SequenceNumber sequence,
LogFileNumberSize & log_file_number_size )
private

db_impl_write.cc 파일의 1602 번째 라인에서 정의되었습니다.

1606 {
1607 IOStatus io_s;
1608 assert(!two_write_queues_);
1609 assert(!write_group.leader->disable_wal);
1610 // Same holds for all in the batch group
1611 size_t write_with_wal = 0;
1612 WriteBatch* to_be_cached_state = nullptr;
1613 WriteBatch* merged_batch;
1614 io_s = status_to_io_status(MergeBatch(write_group, &tmp_batch_, &merged_batch,
1615 &write_with_wal, &to_be_cached_state));
1616 if (UNLIKELY(!io_s.ok())) {
1617 return io_s;
1618 }
1619
1620 if (merged_batch == write_group.leader->batch) {
1621 write_group.leader->log_used = logfile_number_;
1622 } else if (write_with_wal > 1) {
1623 for (auto writer : write_group) {
1624 writer->log_used = logfile_number_;
1625 }
1626 }
1627
1628 WriteBatchInternal::SetSequence(merged_batch, sequence);
1629
1630 uint64_t log_size;
1631
1632 // TODO: plumb Env::IOActivity, Env::IOPriority
1633 WriteOptions write_options;
1634 write_options.rate_limiter_priority =
1635 write_group.leader->rate_limiter_priority;
1636 io_s = WriteToWAL(*merged_batch, write_options, log_writer, log_used,
1637 &log_size, log_file_number_size);
1638 if (to_be_cached_state) {
1639 cached_recoverable_state_ = *to_be_cached_state;
1641 }
1642
1643 if (io_s.ok() && need_log_sync) {
1644 StopWatch sw(immutable_db_options_.clock, stats_, WAL_FILE_SYNC_MICROS);
1645 // It's safe to access logs_ with unlocked mutex_ here because:
1646 // - we've set getting_synced=true for all logs,
1647 // so other threads won't pop from logs_ while we're here,
1648 // - only writer thread can push to logs_, and we're in
1649 // writer thread, so no one will push to logs_,
1650 // - as long as other threads don't modify it, it's safe to read
1651 // from std::deque from multiple threads concurrently.
1652 //
1653 // Sync operation should work with locked log_write_mutex_, because:
1654 // when DBOptions.manual_wal_flush_ is set,
1655 // FlushWAL function will be invoked by another thread.
1656 // if without locked log_write_mutex_, the log file may get data
1657 // corruption
1658
1659 const bool needs_locking = manual_wal_flush_ && !two_write_queues_;
1660 if (UNLIKELY(needs_locking)) {
1662 }
1663
1664 if (io_s.ok()) {
1665 for (auto& log : logs_) {
1666 IOOptions opts;
1667 io_s = WritableFileWriter::PrepareIOOptions(write_options, opts);
1668 if (!io_s.ok()) {
1669 break;
1670 }
1671 // If last sync failed on a later WAL, this could be a fully synced
1672 // and closed WAL that just needs to be recorded as synced in the
1673 // manifest.
1674 if (auto* f = log.writer->file()) {
1675 io_s = f->Sync(opts, immutable_db_options_.use_fsync);
1676 if (!io_s.ok()) {
1677 break;
1678 }
1679 }
1680 }
1681 }
1682
1683 if (UNLIKELY(needs_locking)) {
1685 }
1686
1687 if (io_s.ok() && need_log_dir_sync) {
1688 // We only sync WAL directory the first time WAL syncing is
1689 // requested, so that in case users never turn on WAL sync,
1690 // we can avoid the disk I/O in the write code path.
1692 IOOptions(), nullptr,
1693 DirFsyncOptions(DirFsyncOptions::FsyncReason::kNewFileSynced));
1694 }
1695 }
1696
1697 if (merged_batch == &tmp_batch_) {
1698 tmp_batch_.Clear();
1699 }
1700 if (io_s.ok()) {
1701 auto stats = default_cf_internal_stats_;
1702 if (need_log_sync) {
1703 stats->AddDBStats(InternalStats::kIntStatsWalFileSynced, 1);
1704 RecordTick(stats_, WAL_FILE_SYNCED);
1705 }
1706 stats->AddDBStats(InternalStats::kIntStatsWalFileBytes, log_size);
1707 RecordTick(stats_, WAL_FILE_BYTES, log_size);
1708 stats->AddDBStats(InternalStats::kIntStatsWriteWithWal, write_with_wal);
1709 RecordTick(stats_, WRITE_WITH_WAL, write_with_wal);
1710 for (auto* writer : write_group) {
1711 if (!writer->CallbackFailed()) {
1712 writer->CheckPostWalWriteCallback();
1713 }
1714 }
1715 }
1716 return io_s;
1717}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ WriteWithCallback() [1/2]

Status ROCKSDB_NAMESPACE::DBImpl::WriteWithCallback ( const WriteOptions & options,
WriteBatch * updates,
UserWriteCallback * user_write_cb )
overridevirtual

ROCKSDB_NAMESPACE::DB(으)로부터 재구현되었습니다.

db_impl_write.cc 파일의 179 번째 라인에서 정의되었습니다.

181 {
182 Status s;
183 if (write_options.protection_bytes_per_key > 0) {
184 s = WriteBatchInternal::UpdateProtectionInfo(
185 my_batch, write_options.protection_bytes_per_key);
186 }
187 if (s.ok()) {
188 s = WriteImpl(write_options, my_batch, /*callback=*/nullptr, user_write_cb);
189 }
190 return s;
191}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ WriteWithCallback() [2/2]

Status ROCKSDB_NAMESPACE::DBImpl::WriteWithCallback ( const WriteOptions & write_options,
WriteBatch * my_batch,
WriteCallback * callback,
UserWriteCallback * user_write_cb = nullptr )
virtual

db_impl_write.cc 파일의 165 번째 라인에서 정의되었습니다.

167 {
168 Status s;
169 if (write_options.protection_bytes_per_key > 0) {
170 s = WriteBatchInternal::UpdateProtectionInfo(
171 my_batch, write_options.protection_bytes_per_key);
172 }
173 if (s.ok()) {
174 s = WriteImpl(write_options, my_batch, callback, user_write_cb);
175 }
176 return s;
177}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

Friend, 그리고 관련된 함수 문서화

◆ CompactedDBImpl

friend class CompactedDBImpl
friend

db_impl.h 파일의 1718 번째 라인에서 정의되었습니다.

◆ CompactionServiceTest_PreservedOptionsLocalCompaction_Test

friend class CompactionServiceTest_PreservedOptionsLocalCompaction_Test
friend

db_impl.h 파일의 1733 번째 라인에서 정의되었습니다.

◆ CompactionServiceTest_PreservedOptionsRemoteCompaction_Test

friend class CompactionServiceTest_PreservedOptionsRemoteCompaction_Test
friend

db_impl.h 파일의 1734 번째 라인에서 정의되었습니다.

◆ DB

friend class DB
friend

db_impl.h 파일의 1704 번째 라인에서 정의되었습니다.

◆ DBBlobIndexTest

friend class DBBlobIndexTest
friend

db_impl.h 파일의 1731 번째 라인에서 정의되었습니다.

◆ DBCompactionTest_CompactBottomLevelFilesWithDeletions_Test

friend class DBCompactionTest_CompactBottomLevelFilesWithDeletions_Test
friend

db_impl.h 파일의 1723 번째 라인에서 정의되었습니다.

◆ DBCompactionTest_CompactionDuringShutdown_Test

friend class DBCompactionTest_CompactionDuringShutdown_Test
friend

db_impl.h 파일의 1724 번째 라인에서 정의되었습니다.

◆ DBCompactionTest_DelayCompactBottomLevelFilesWithDeletions_Test

friend class DBCompactionTest_DelayCompactBottomLevelFilesWithDeletions_Test
friend

db_impl.h 파일의 1725 번째 라인에서 정의되었습니다.

◆ DBCompactionTest_DisableCompactBottomLevelFiles_Test

friend class DBCompactionTest_DisableCompactBottomLevelFiles_Test
friend

db_impl.h 파일의 1726 번째 라인에서 정의되었습니다.

◆ DBImplFollower

friend class DBImplFollower
friend

db_impl.h 파일의 1719 번째 라인에서 정의되었습니다.

◆ DBTest2_ReadCallbackTest_Test

friend class DBTest2_ReadCallbackTest_Test
friend

db_impl.h 파일의 1728 번째 라인에서 정의되었습니다.

◆ DBTest_ConcurrentFlushWAL_Test

friend class DBTest_ConcurrentFlushWAL_Test
friend

db_impl.h 파일의 1721 번째 라인에서 정의되었습니다.

◆ DBTest_MixedSlowdownOptionsStop_Test

friend class DBTest_MixedSlowdownOptionsStop_Test
friend

db_impl.h 파일의 1722 번째 라인에서 정의되었습니다.

◆ ErrorHandler

friend class ErrorHandler
friend

db_impl.h 파일의 1705 번째 라인에서 정의되었습니다.

◆ ForwardIterator

friend class ForwardIterator
friend

db_impl.h 파일의 1716 번째 라인에서 정의되었습니다.

◆ InternalStats

friend class InternalStats
friend

db_impl.h 파일의 1706 번째 라인에서 정의되었습니다.

◆ PessimisticTransaction

friend class PessimisticTransaction
friend

db_impl.h 파일의 1707 번째 라인에서 정의되었습니다.

◆ StatsHistoryTest_PersistentStatsCreateColumnFamilies_Test

friend class StatsHistoryTest_PersistentStatsCreateColumnFamilies_Test
friend

db_impl.h 파일의 1727 번째 라인에서 정의되었습니다.

◆ SuperVersion

friend struct SuperVersion
friend

db_impl.h 파일의 1717 번째 라인에서 정의되었습니다.

◆ TransactionBaseImpl

friend class TransactionBaseImpl
friend

db_impl.h 파일의 1708 번째 라인에서 정의되었습니다.

◆ WriteBatchWithIndex

friend class WriteBatchWithIndex
friend

db_impl.h 파일의 1712 번째 라인에서 정의되었습니다.

◆ WriteCallbackPTest_WriteWithCallbackTest_Test

friend class WriteCallbackPTest_WriteWithCallbackTest_Test
friend

db_impl.h 파일의 1729 번째 라인에서 정의되었습니다.

◆ WriteCommittedTxn

friend class WriteCommittedTxn
friend

db_impl.h 파일의 1709 번째 라인에서 정의되었습니다.

◆ WritePreparedTxn

friend class WritePreparedTxn
friend

db_impl.h 파일의 1710 번째 라인에서 정의되었습니다.

◆ WritePreparedTxnDB

friend class WritePreparedTxnDB
friend

db_impl.h 파일의 1711 번째 라인에서 정의되었습니다.

◆ WriteUnpreparedTransactionTest_RecoveryTest_Test

friend class WriteUnpreparedTransactionTest_RecoveryTest_Test
friend

db_impl.h 파일의 1732 번째 라인에서 정의되었습니다.

◆ WriteUnpreparedTxn

friend class WriteUnpreparedTxn
friend

db_impl.h 파일의 1714 번째 라인에서 정의되었습니다.

◆ WriteUnpreparedTxnDB

friend class WriteUnpreparedTxnDB
friend

db_impl.h 파일의 1713 번째 라인에서 정의되었습니다.

◆ XFTransactionWriteHandler

friend class XFTransactionWriteHandler
friend

db_impl.h 파일의 1730 번째 라인에서 정의되었습니다.

멤버 데이터 문서화

◆ alive_log_files_

std::deque<LogFileNumberSize> ROCKSDB_NAMESPACE::DBImpl::alive_log_files_
private

db_impl.h 파일의 2696 번째 라인에서 정의되었습니다.

◆ atomic_flush_install_cv_

InstrumentedCondVar ROCKSDB_NAMESPACE::DBImpl::atomic_flush_install_cv_
private

db_impl.h 파일의 3003 번째 라인에서 정의되었습니다.

◆ batch_per_txn_

const bool ROCKSDB_NAMESPACE::DBImpl::batch_per_txn_
protected

db_impl.h 파일의 1412 번째 라인에서 정의되었습니다.

◆ bg_bottom_compaction_scheduled_

int ROCKSDB_NAMESPACE::DBImpl::bg_bottom_compaction_scheduled_
private

db_impl.h 파일의 2863 번째 라인에서 정의되었습니다.

◆ bg_compaction_paused_

int ROCKSDB_NAMESPACE::DBImpl::bg_compaction_paused_
private

db_impl.h 파일의 2930 번째 라인에서 정의되었습니다.

◆ bg_compaction_scheduled_

int ROCKSDB_NAMESPACE::DBImpl::bg_compaction_scheduled_
private

db_impl.h 파일의 2866 번째 라인에서 정의되었습니다.

◆ bg_cv_

InstrumentedCondVar ROCKSDB_NAMESPACE::DBImpl::bg_cv_
private

db_impl.h 파일의 2637 번째 라인에서 정의되었습니다.

◆ bg_flush_scheduled_

int ROCKSDB_NAMESPACE::DBImpl::bg_flush_scheduled_
private

db_impl.h 파일의 2872 번째 라인에서 정의되었습니다.

◆ bg_purge_scheduled_

int ROCKSDB_NAMESPACE::DBImpl::bg_purge_scheduled_
private

db_impl.h 파일의 2878 번째 라인에서 정의되었습니다.

◆ bg_work_paused_

int ROCKSDB_NAMESPACE::DBImpl::bg_work_paused_
private

db_impl.h 파일의 2927 번째 라인에서 정의되었습니다.

◆ blob_callback_

BlobFileCompletionCallback ROCKSDB_NAMESPACE::DBImpl::blob_callback_
private

db_impl.h 파일의 3008 번째 라인에서 정의되었습니다.

◆ block_cache_tracer_

BlockCacheTracer ROCKSDB_NAMESPACE::DBImpl::block_cache_tracer_
protected

db_impl.h 파일의 1361 번째 라인에서 정의되었습니다.

◆ bottommost_files_mark_threshold_

SequenceNumber ROCKSDB_NAMESPACE::DBImpl::bottommost_files_mark_threshold_ = kMaxSequenceNumber
private

db_impl.h 파일의 2940 번째 라인에서 정의되었습니다.

◆ cached_recoverable_state_

WriteBatch ROCKSDB_NAMESPACE::DBImpl::cached_recoverable_state_
private

db_impl.h 파일의 2762 번째 라인에서 정의되었습니다.

◆ cached_recoverable_state_empty_

std::atomic<bool> ROCKSDB_NAMESPACE::DBImpl::cached_recoverable_state_empty_ = {true}
private

db_impl.h 파일의 2763 번째 라인에서 정의되었습니다.

2763{true};

◆ closed_

bool ROCKSDB_NAMESPACE::DBImpl::closed_
private

db_impl.h 파일의 2988 번째 라인에서 정의되었습니다.

◆ closing_mutex_

InstrumentedMutex ROCKSDB_NAMESPACE::DBImpl::closing_mutex_
private

db_impl.h 파일의 2992 번째 라인에서 정의되었습니다.

◆ closing_status_

Status ROCKSDB_NAMESPACE::DBImpl::closing_status_
private

db_impl.h 파일의 2990 번째 라인에서 정의되었습니다.

◆ column_family_memtables_

std::unique_ptr<ColumnFamilyMemTablesImpl> ROCKSDB_NAMESPACE::DBImpl::column_family_memtables_
protected

db_impl.h 파일의 1397 번째 라인에서 정의되었습니다.

◆ compaction_queue_

std::deque<ColumnFamilyData*> ROCKSDB_NAMESPACE::DBImpl::compaction_queue_
private

db_impl.h 파일의 2843 번째 라인에서 정의되었습니다.

◆ db_id_

std::string ROCKSDB_NAMESPACE::DBImpl::db_id_
protected

db_impl.h 파일의 1342 번째 라인에서 정의되었습니다.

◆ db_lock_

FileLock* ROCKSDB_NAMESPACE::DBImpl::db_lock_
private

db_impl.h 파일의 2595 번째 라인에서 정의되었습니다.

◆ db_session_id_

std::string ROCKSDB_NAMESPACE::DBImpl::db_session_id_
protected

db_impl.h 파일의 1345 번째 라인에서 정의되었습니다.

◆ dbname_

const std::string ROCKSDB_NAMESPACE::DBImpl::dbname_
protected

db_impl.h 파일의 1340 번째 라인에서 정의되었습니다.

◆ default_cf_handle_

ColumnFamilyHandleImpl* ROCKSDB_NAMESPACE::DBImpl::default_cf_handle_
protected

db_impl.h 파일의 1376 번째 라인에서 정의되었습니다.

◆ default_cf_internal_stats_

InternalStats* ROCKSDB_NAMESPACE::DBImpl::default_cf_internal_stats_
protected

db_impl.h 파일의 1377 번째 라인에서 정의되었습니다.

◆ delete_obsolete_files_last_run_

uint64_t ROCKSDB_NAMESPACE::DBImpl::delete_obsolete_files_last_run_
private

db_impl.h 파일의 2896 번째 라인에서 정의되었습니다.

◆ directories_

Directories ROCKSDB_NAMESPACE::DBImpl::directories_
private

db_impl.h 파일의 2778 번째 라인에서 정의되었습니다.

◆ disable_delete_obsolete_files_

int ROCKSDB_NAMESPACE::DBImpl::disable_delete_obsolete_files_
private

db_impl.h 파일의 2888 번째 라인에서 정의되었습니다.

◆ env_

Env* const ROCKSDB_NAMESPACE::DBImpl::env_
protected

db_impl.h 파일의 1351 번째 라인에서 정의되었습니다.

◆ error_handler_

ErrorHandler ROCKSDB_NAMESPACE::DBImpl::error_handler_
protected

db_impl.h 파일의 1382 번째 라인에서 정의되었습니다.

◆ event_logger_

EventLogger ROCKSDB_NAMESPACE::DBImpl::event_logger_
protected

db_impl.h 파일의 1385 번째 라인에서 정의되었습니다.

◆ file_options_

const FileOptions ROCKSDB_NAMESPACE::DBImpl::file_options_
protected

db_impl.h 파일의 1392 번째 라인에서 정의되었습니다.

◆ file_options_for_compaction_

FileOptions ROCKSDB_NAMESPACE::DBImpl::file_options_for_compaction_
protected

db_impl.h 파일의 1395 번째 라인에서 정의되었습니다.

◆ files_grabbed_for_purge_

std::unordered_set<uint64_t> ROCKSDB_NAMESPACE::DBImpl::files_grabbed_for_purge_
private

db_impl.h 파일의 2850 번째 라인에서 정의되었습니다.

◆ flush_queue_

std::deque<FlushRequest> ROCKSDB_NAMESPACE::DBImpl::flush_queue_
private

db_impl.h 파일의 2840 번째 라인에서 정의되었습니다.

◆ flush_scheduler_

FlushScheduler ROCKSDB_NAMESPACE::DBImpl::flush_scheduler_
private

db_impl.h 파일의 2796 번째 라인에서 정의되었습니다.

◆ fs_

FileSystemPtr ROCKSDB_NAMESPACE::DBImpl::fs_
protected

db_impl.h 파일의 1354 번째 라인에서 정의되었습니다.

◆ has_unpersisted_data_

std::atomic<bool> ROCKSDB_NAMESPACE::DBImpl::has_unpersisted_data_
private

db_impl.h 파일의 2909 번째 라인에서 정의되었습니다.

◆ immutable_db_options_

const ImmutableDBOptions ROCKSDB_NAMESPACE::DBImpl::immutable_db_options_
protected

db_impl.h 파일의 1353 번째 라인에서 정의되었습니다.

◆ init_logger_creation_s_

Status ROCKSDB_NAMESPACE::DBImpl::init_logger_creation_s_
protected

db_impl.h 파일의 1349 번째 라인에서 정의되었습니다.

◆ initial_db_options_

const DBOptions ROCKSDB_NAMESPACE::DBImpl::initial_db_options_
protected

db_impl.h 파일의 1350 번째 라인에서 정의되었습니다.

◆ io_tracer_

std::shared_ptr<IOTracer> ROCKSDB_NAMESPACE::DBImpl::io_tracer_
protected

db_impl.h 파일의 1352 번째 라인에서 정의되었습니다.

◆ is_snapshot_supported_

bool ROCKSDB_NAMESPACE::DBImpl::is_snapshot_supported_
private

db_impl.h 파일의 2770 번째 라인에서 정의되었습니다.

◆ kManualCompactionCanceledFalse_

const std::atomic<bool> ROCKSDB_NAMESPACE::DBImpl::kManualCompactionCanceledFalse_ {false}
protected

db_impl.h 파일의 1364 번째 라인에서 정의되었습니다.

1364{false};

◆ last_batch_group_size_

uint64_t ROCKSDB_NAMESPACE::DBImpl::last_batch_group_size_
private

db_impl.h 파일의 2794 번째 라인에서 정의되었습니다.

◆ last_seq_same_as_publish_seq_

const bool ROCKSDB_NAMESPACE::DBImpl::last_seq_same_as_publish_seq_
private

db_impl.h 파일의 2971 번째 라인에서 정의되었습니다.

◆ lock_wal_count_

uint32_t ROCKSDB_NAMESPACE::DBImpl::lock_wal_count_
private

db_impl.h 파일의 3024 번째 라인에서 정의되었습니다.

◆ lock_wal_write_token_

std::unique_ptr<WriteControllerToken> ROCKSDB_NAMESPACE::DBImpl::lock_wal_write_token_
private

db_impl.h 파일의 3020 번째 라인에서 정의되었습니다.

◆ log_dir_synced_

bool ROCKSDB_NAMESPACE::DBImpl::log_dir_synced_
private

db_impl.h 파일의 2651 번째 라인에서 정의되었습니다.

◆ log_empty_

bool ROCKSDB_NAMESPACE::DBImpl::log_empty_
private

db_impl.h 파일의 2658 번째 라인에서 정의되었습니다.

◆ log_recycle_files_

std::deque<uint64_t> ROCKSDB_NAMESPACE::DBImpl::log_recycle_files_
private

db_impl.h 파일의 2644 번째 라인에서 정의되었습니다.

◆ log_sync_cv_

InstrumentedCondVar ROCKSDB_NAMESPACE::DBImpl::log_sync_cv_
private

db_impl.h 파일의 2754 번째 라인에서 정의되었습니다.

◆ log_write_mutex_

InstrumentedMutex ROCKSDB_NAMESPACE::DBImpl::log_write_mutex_
private

db_impl.h 파일의 2615 번째 라인에서 정의되었습니다.

◆ logfile_number_

uint64_t ROCKSDB_NAMESPACE::DBImpl::logfile_number_
private

db_impl.h 파일의 2642 번째 라인에서 정의되었습니다.

◆ logs_

std::deque<LogWriterNumber> ROCKSDB_NAMESPACE::DBImpl::logs_
private

db_impl.h 파일의 2751 번째 라인에서 정의되었습니다.

◆ logs_to_free_

autovector<log::Writer*> ROCKSDB_NAMESPACE::DBImpl::logs_to_free_
private

db_impl.h 파일의 2768 번째 라인에서 정의되었습니다.

◆ logs_to_free_queue_

std::deque<log::Writer*> ROCKSDB_NAMESPACE::DBImpl::logs_to_free_queue_
private

db_impl.h 파일의 2853 번째 라인에서 정의되었습니다.

◆ logs_with_prep_tracker_

LogsWithPrepTracker ROCKSDB_NAMESPACE::DBImpl::logs_with_prep_tracker_
private

db_impl.h 파일의 2947 번째 라인에서 정의되었습니다.

◆ manual_compaction_dequeue_

std::deque<ManualCompactionState*> ROCKSDB_NAMESPACE::DBImpl::manual_compaction_dequeue_
private

db_impl.h 파일의 2880 번째 라인에서 정의되었습니다.

◆ manual_compaction_paused_

std::atomic<int> ROCKSDB_NAMESPACE::DBImpl::manual_compaction_paused_
private

db_impl.h 파일의 2622 번째 라인에서 정의되었습니다.

◆ manual_wal_flush_

const bool ROCKSDB_NAMESPACE::DBImpl::manual_wal_flush_
private

db_impl.h 파일의 2967 번째 라인에서 정의되었습니다.

◆ max_total_in_memory_state_

std::atomic<uint64_t> ROCKSDB_NAMESPACE::DBImpl::max_total_in_memory_state_
protected

db_impl.h 파일의 1389 번째 라인에서 정의되었습니다.

◆ max_total_wal_size_

std::atomic<uint64_t> ROCKSDB_NAMESPACE::DBImpl::max_total_wal_size_
private

db_impl.h 파일의 3006 번째 라인에서 정의되었습니다.

◆ min_log_number_to_recycle_

uint64_t ROCKSDB_NAMESPACE::DBImpl::min_log_number_to_recycle_
private

db_impl.h 파일의 2649 번째 라인에서 정의되었습니다.

◆ min_options_file_numbers_

std::list<uint64_t> ROCKSDB_NAMESPACE::DBImpl::min_options_file_numbers_
private

db_impl.h 파일의 2818 번째 라인에서 정의되었습니다.

◆ mutable_db_options_

MutableDBOptions ROCKSDB_NAMESPACE::DBImpl::mutable_db_options_
protected

db_impl.h 파일의 1355 번째 라인에서 정의되었습니다.

◆ mutex_

CacheAlignedInstrumentedMutex ROCKSDB_NAMESPACE::DBImpl::mutex_
mutableprotected

db_impl.h 파일의 1374 번째 라인에서 정의되었습니다.

◆ next_job_id_

std::atomic<int> ROCKSDB_NAMESPACE::DBImpl::next_job_id_
protected

db_impl.h 파일의 1416 번째 라인에서 정의되었습니다.

◆ nonmem_write_thread_

WriteThread ROCKSDB_NAMESPACE::DBImpl::nonmem_write_thread_
private

db_impl.h 파일의 2786 번째 라인에서 정의되었습니다.

◆ num_running_compactions_

int ROCKSDB_NAMESPACE::DBImpl::num_running_compactions_
private

db_impl.h 파일의 2869 번째 라인에서 정의되었습니다.

◆ num_running_flushes_

int ROCKSDB_NAMESPACE::DBImpl::num_running_flushes_
private

db_impl.h 파일의 2875 번째 라인에서 정의되었습니다.

◆ num_running_ingest_file_

int ROCKSDB_NAMESPACE::DBImpl::num_running_ingest_file_
private

db_impl.h 파일의 2922 번째 라인에서 정의되었습니다.

◆ opened_successfully_

bool ROCKSDB_NAMESPACE::DBImpl::opened_successfully_
private

db_impl.h 파일의 2936 번째 라인에서 정의되었습니다.

◆ options_mutex_

InstrumentedMutex ROCKSDB_NAMESPACE::DBImpl::options_mutex_
private

db_impl.h 파일의 2604 번째 라인에서 정의되었습니다.

◆ own_info_log_

bool ROCKSDB_NAMESPACE::DBImpl::own_info_log_
protected

db_impl.h 파일의 1348 번째 라인에서 정의되었습니다.

◆ own_sfm_

bool ROCKSDB_NAMESPACE::DBImpl::own_sfm_
private

db_impl.h 파일의 2985 번째 라인에서 정의되었습니다.

◆ pending_memtable_writes_

std::atomic<size_t> ROCKSDB_NAMESPACE::DBImpl::pending_memtable_writes_ = {}
private

db_impl.h 파일의 2904 번째 라인에서 정의되었습니다.

2904{};

◆ pending_outputs_

std::list<uint64_t> ROCKSDB_NAMESPACE::DBImpl::pending_outputs_
private

db_impl.h 파일의 2813 번째 라인에서 정의되었습니다.

◆ pending_purge_obsolete_files_

int ROCKSDB_NAMESPACE::DBImpl::pending_purge_obsolete_files_
private

db_impl.h 파일의 2892 번째 라인에서 정의되었습니다.

◆ periodic_task_functions_

std::map<PeriodicTaskType, const PeriodicTaskFunc> ROCKSDB_NAMESPACE::DBImpl::periodic_task_functions_
private

db_impl.h 파일의 2962 번째 라인에서 정의되었습니다.

◆ periodic_task_scheduler_

PeriodicTaskScheduler ROCKSDB_NAMESPACE::DBImpl::periodic_task_scheduler_
private

db_impl.h 파일의 2959 번째 라인에서 정의되었습니다.

◆ persist_stats_cf_handle_

ColumnFamilyHandleImpl* ROCKSDB_NAMESPACE::DBImpl::persist_stats_cf_handle_
private

db_impl.h 파일의 2660 번째 라인에서 정의되었습니다.

◆ persistent_stats_cfd_exists_

bool ROCKSDB_NAMESPACE::DBImpl::persistent_stats_cfd_exists_ = true
private

db_impl.h 파일의 2662 번째 라인에서 정의되었습니다.

◆ purge_files_

std::unordered_map<uint64_t, PurgeFileInfo> ROCKSDB_NAMESPACE::DBImpl::purge_files_
private

db_impl.h 파일의 2846 번째 라인에서 정의되었습니다.

◆ recoverable_state_pre_release_callback_

std::unique_ptr<PreReleaseCallback> ROCKSDB_NAMESPACE::DBImpl::recoverable_state_pre_release_callback_
private

db_impl.h 파일의 2955 번째 라인에서 정의되었습니다.

◆ recovered_transactions_

std::unordered_map<std::string, RecoveredTransaction*> ROCKSDB_NAMESPACE::DBImpl::recovered_transactions_
protected

db_impl.h 파일의 1358 번째 라인에서 정의되었습니다.

◆ refitting_level_

bool ROCKSDB_NAMESPACE::DBImpl::refitting_level_
private

db_impl.h 파일의 2933 번째 라인에서 정의되었습니다.

◆ reject_new_background_jobs_

bool ROCKSDB_NAMESPACE::DBImpl::reject_new_background_jobs_
protected

db_impl.h 파일의 1423 번째 라인에서 정의되었습니다.

◆ seq_per_batch_

const bool ROCKSDB_NAMESPACE::DBImpl::seq_per_batch_
protected

db_impl.h 파일의 1405 번째 라인에서 정의되었습니다.

◆ seqno_to_time_mapping_

SeqnoToTimeMapping ROCKSDB_NAMESPACE::DBImpl::seqno_to_time_mapping_
private

db_impl.h 파일의 3015 번째 라인에서 정의되었습니다.

◆ shutdown_initiated_

std::atomic<bool> ROCKSDB_NAMESPACE::DBImpl::shutdown_initiated_
private

db_impl.h 파일의 2982 번째 라인에서 정의되었습니다.

◆ shutting_down_

std::atomic<bool> ROCKSDB_NAMESPACE::DBImpl::shutting_down_
protected

db_impl.h 파일의 1418 번째 라인에서 정의되었습니다.

◆ snapshot_checker_

std::unique_ptr<SnapshotChecker> ROCKSDB_NAMESPACE::DBImpl::snapshot_checker_
private

db_impl.h 파일의 2951 번째 라인에서 정의되었습니다.

◆ snapshots_

SnapshotList ROCKSDB_NAMESPACE::DBImpl::snapshots_
private

db_impl.h 파일의 2800 번째 라인에서 정의되었습니다.

◆ standalone_range_deletion_files_mark_threshold_

SequenceNumber ROCKSDB_NAMESPACE::DBImpl::standalone_range_deletion_files_mark_threshold_
private
초기값:
=
static const SequenceNumber kMaxSequenceNumber
Definition dbformat.h:128

db_impl.h 파일의 2944 번째 라인에서 정의되었습니다.

◆ stats_

Statistics* ROCKSDB_NAMESPACE::DBImpl::stats_
protected

db_impl.h 파일의 1356 번째 라인에서 정의되었습니다.

◆ stats_history_

std::map<uint64_t, std::map<std::string, uint64_t> > ROCKSDB_NAMESPACE::DBImpl::stats_history_
private

db_impl.h 파일의 2772 번째 라인에서 정의되었습니다.

◆ stats_history_mutex_

InstrumentedMutex ROCKSDB_NAMESPACE::DBImpl::stats_history_mutex_
private

db_impl.h 파일의 2607 번째 라인에서 정의되었습니다.

◆ stats_slice_

std::map<std::string, uint64_t> ROCKSDB_NAMESPACE::DBImpl::stats_slice_
private

db_impl.h 파일의 2774 번째 라인에서 정의되었습니다.

◆ stats_slice_initialized_

bool ROCKSDB_NAMESPACE::DBImpl::stats_slice_initialized_ = false
private

db_impl.h 파일의 2776 번째 라인에서 정의되었습니다.

◆ superversions_to_free_queue_

std::deque<SuperVersion*> ROCKSDB_NAMESPACE::DBImpl::superversions_to_free_queue_
private

db_impl.h 파일의 2855 번째 라인에서 정의되었습니다.

◆ switch_cv_

std::condition_variable ROCKSDB_NAMESPACE::DBImpl::switch_cv_
private

db_impl.h 파일의 2900 번째 라인에서 정의되었습니다.

◆ switch_mutex_

std::mutex ROCKSDB_NAMESPACE::DBImpl::switch_mutex_
private

db_impl.h 파일의 2902 번째 라인에서 정의되었습니다.

◆ table_cache_

std::shared_ptr<Cache> ROCKSDB_NAMESPACE::DBImpl::table_cache_
protected

db_impl.h 파일의 1380 번째 라인에서 정의되었습니다.

◆ timestamped_snapshots_

TimestampedSnapshotList ROCKSDB_NAMESPACE::DBImpl::timestamped_snapshots_
private

db_impl.h 파일의 2802 번째 라인에서 정의되었습니다.

◆ tmp_batch_

WriteBatch ROCKSDB_NAMESPACE::DBImpl::tmp_batch_
private

db_impl.h 파일의 2783 번째 라인에서 정의되었습니다.

◆ total_log_size_

std::atomic<uint64_t> ROCKSDB_NAMESPACE::DBImpl::total_log_size_
private

db_impl.h 파일의 2764 번째 라인에서 정의되었습니다.

◆ trace_mutex_

InstrumentedMutex ROCKSDB_NAMESPACE::DBImpl::trace_mutex_
protected

db_impl.h 파일의 1360 번째 라인에서 정의되었습니다.

◆ tracer_

std::unique_ptr<Tracer> ROCKSDB_NAMESPACE::DBImpl::tracer_
protected

db_impl.h 파일의 1359 번째 라인에서 정의되었습니다.

◆ trim_history_scheduler_

TrimHistoryScheduler ROCKSDB_NAMESPACE::DBImpl::trim_history_scheduler_
private

db_impl.h 파일의 2798 번째 라인에서 정의되었습니다.

◆ two_write_queues_

const bool ROCKSDB_NAMESPACE::DBImpl::two_write_queues_
private

db_impl.h 파일의 2966 번째 라인에서 정의되었습니다.

◆ unable_to_release_oldest_log_

bool ROCKSDB_NAMESPACE::DBImpl::unable_to_release_oldest_log_
private

db_impl.h 파일의 2917 번째 라인에서 정의되었습니다.

◆ unscheduled_compactions_

int ROCKSDB_NAMESPACE::DBImpl::unscheduled_compactions_
private

db_impl.h 파일의 2859 번째 라인에서 정의되었습니다.

◆ unscheduled_flushes_

int ROCKSDB_NAMESPACE::DBImpl::unscheduled_flushes_
private

db_impl.h 파일의 2857 번째 라인에서 정의되었습니다.

◆ use_custom_gc_

const bool ROCKSDB_NAMESPACE::DBImpl::use_custom_gc_
private

db_impl.h 파일의 2975 번째 라인에서 정의되었습니다.

◆ versions_

std::unique_ptr<VersionSet> ROCKSDB_NAMESPACE::DBImpl::versions_
protected

db_impl.h 파일의 1346 번째 라인에서 정의되었습니다.

◆ wal_in_db_path_

bool ROCKSDB_NAMESPACE::DBImpl::wal_in_db_path_
private

db_impl.h 파일의 3005 번째 라인에서 정의되었습니다.

◆ wal_manager_

WalManager ROCKSDB_NAMESPACE::DBImpl::wal_manager_
private

db_impl.h 파일의 2924 번째 라인에서 정의되었습니다.

◆ wbm_stall_

std::unique_ptr<StallInterface> ROCKSDB_NAMESPACE::DBImpl::wbm_stall_
private

db_impl.h 파일의 3011 번째 라인에서 정의되었습니다.

◆ write_buffer_manager_

WriteBufferManager* ROCKSDB_NAMESPACE::DBImpl::write_buffer_manager_
private

db_impl.h 파일의 2780 번째 라인에서 정의되었습니다.

◆ write_controller_

WriteController ROCKSDB_NAMESPACE::DBImpl::write_controller_
private

db_impl.h 파일의 2788 번째 라인에서 정의되었습니다.

◆ write_thread_

WriteThread ROCKSDB_NAMESPACE::DBImpl::write_thread_
private

db_impl.h 파일의 2782 번째 라인에서 정의되었습니다.


이 클래스에 대한 문서화 페이지는 다음의 파일들로부터 생성되었습니다.: